Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[X86] Add test cases for missing propagation of fpexcept flag on stri…
…ct fp operations. NFC The flag is being lost during type legalization or lowering. This covers some of the cases. I'm sure there are many missing.
- Loading branch information
Showing
3 changed files
with
191 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
; RUN: llc -O3 -mtriple=x86_64-pc-linux < %s -stop-after=finalize-isel | FileCheck %s | ||
|
||
define i32 @f20u(double %x) #0 { | ||
; CHECK-LABEL: name: f20u | ||
; CHECK: liveins: $xmm0 | ||
; CHECK: [[COPY:%[0-9]+]]:fr64 = COPY $xmm0 | ||
; CHECK: [[CVTTSD2SI64rr:%[0-9]+]]:gr64 = CVTTSD2SI64rr [[COPY]], implicit $mxcsr | ||
; CHECK: [[COPY1:%[0-9]+]]:gr32 = COPY [[CVTTSD2SI64rr]].sub_32bit | ||
; CHECK: $eax = COPY [[COPY1]] | ||
; CHECK: RET 0, $eax | ||
entry: | ||
%result = call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %x, metadata !"fpexcept.strict") #0 | ||
ret i32 %result | ||
} | ||
|
||
attributes #0 = { strictfp } | ||
|
||
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
; RUN: llc -O3 -mtriple=i686-pc-linux -mattr=sse2 -stop-after=finalize-isel < %s | FileCheck %s | ||
|
||
define double @sifdb(i8 %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: sifdb | ||
; CHECK: [[MOVSX32rm8_:%[0-9]+]]:gr32 = MOVSX32rm8 %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 1 from %fixed-stack.0, align 16) | ||
; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = CVTSI2SDrr killed [[MOVSX32rm8_]] | ||
; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[CVTSI2SDrr]] :: (store 8 into %stack.0, align 4) | ||
; CHECK: [[LD_Fp64m80_:%[0-9]+]]:rfp80 = LD_Fp64m80 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0, align 4) | ||
; CHECK: RET 0, killed [[LD_Fp64m80_]] | ||
%result = call double @llvm.experimental.constrained.sitofp.f64.i8(i8 %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 | ||
ret double %result | ||
} | ||
|
||
define double @sifdw(i16 %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: sifdw | ||
; CHECK: [[MOVSX32rm16_:%[0-9]+]]:gr32 = MOVSX32rm16 %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 2 from %fixed-stack.0, align 16) | ||
; CHECK: [[CVTSI2SDrr:%[0-9]+]]:fr64 = CVTSI2SDrr killed [[MOVSX32rm16_]] | ||
; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[CVTSI2SDrr]] :: (store 8 into %stack.0, align 4) | ||
; CHECK: [[LD_Fp64m80_:%[0-9]+]]:rfp80 = LD_Fp64m80 %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0, align 4) | ||
; CHECK: RET 0, killed [[LD_Fp64m80_]] | ||
%result = call double @llvm.experimental.constrained.sitofp.f64.i16(i16 %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 | ||
ret double %result | ||
} | ||
|
||
define i64 @f20u64(double %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: f20u64 | ||
; CHECK: [[MOVSDrm_alt:%[0-9]+]]:fr64 = MOVSDrm_alt %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 8 from %fixed-stack.0, align 16) | ||
; CHECK: [[MOVSDrm_alt1:%[0-9]+]]:fr64 = MOVSDrm_alt $noreg, 1, $noreg, %const.0, $noreg :: (load 8 from constant-pool) | ||
; CHECK: [[CMPSDrr:%[0-9]+]]:fr64 = CMPSDrr [[MOVSDrm_alt]], [[MOVSDrm_alt1]], 1, implicit $mxcsr | ||
; CHECK: [[COPY:%[0-9]+]]:vr128 = COPY [[CMPSDrr]] | ||
; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[MOVSDrm_alt1]] | ||
; CHECK: [[PANDNrr:%[0-9]+]]:vr128 = PANDNrr [[COPY]], killed [[COPY1]] | ||
; CHECK: [[COPY2:%[0-9]+]]:fr64 = COPY [[PANDNrr]] | ||
; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr | ||
; CHECK: MOVSDmr %stack.0, 1, $noreg, 0, $noreg, killed [[SUBSDrr]] :: (store 8 into %stack.0) | ||
; CHECK: [[LD_Fp64m:%[0-9]+]]:rfp64 = LD_Fp64m %stack.0, 1, $noreg, 0, $noreg, implicit-def dead $fpsw, implicit $fpcw :: (load 8 from %stack.0) | ||
; CHECK: FNSTCW16m %stack.1, 1, $noreg, 0, $noreg, implicit-def $fpsw, implicit $fpcw :: (store 2 into %stack.1) | ||
; CHECK: [[MOVZX32rm16_:%[0-9]+]]:gr32 = MOVZX32rm16 %stack.1, 1, $noreg, 0, $noreg :: (load 2 from %stack.1) | ||
; CHECK: [[OR32ri:%[0-9]+]]:gr32 = OR32ri killed [[MOVZX32rm16_]], 3072, implicit-def $eflags | ||
; CHECK: [[COPY3:%[0-9]+]]:gr16 = COPY killed [[OR32ri]].sub_16bit | ||
; CHECK: MOV16mr %stack.2, 1, $noreg, 0, $noreg, killed [[COPY3]] :: (store 2 into %stack.2) | ||
; CHECK: FLDCW16m %stack.2, 1, $noreg, 0, $noreg, implicit-def $fpsw, implicit-def $fpcw :: (load 2 from %stack.2) | ||
; CHECK: IST_Fp64m64 %stack.0, 1, $noreg, 0, $noreg, [[LD_Fp64m]], implicit-def $fpsw, implicit $fpcw | ||
; CHECK: FLDCW16m %stack.1, 1, $noreg, 0, $noreg, implicit-def $fpsw, implicit-def $fpcw :: (load 2 from %stack.1) | ||
; CHECK: UCOMISDrr [[MOVSDrm_alt1]], [[MOVSDrm_alt]], implicit-def $eflags, implicit $mxcsr | ||
; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 6, implicit $eflags | ||
; CHECK: [[MOVZX32rr8_:%[0-9]+]]:gr32 = MOVZX32rr8 killed [[SETCCr]] | ||
; CHECK: [[SHL32ri:%[0-9]+]]:gr32 = SHL32ri [[MOVZX32rr8_]], 31, implicit-def dead $eflags | ||
; CHECK: [[XOR32rm:%[0-9]+]]:gr32 = XOR32rm [[SHL32ri]], %stack.0, 1, $noreg, 4, $noreg, implicit-def dead $eflags :: (load 4 from %stack.0 + 4) | ||
; CHECK: [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm %stack.0, 1, $noreg, 0, $noreg :: (load 4 from %stack.0, align 8) | ||
; CHECK: $eax = COPY [[MOV32rm]] | ||
; CHECK: $edx = COPY [[XOR32rm]] | ||
; CHECK: RET 0, $eax, $edx | ||
%result = call i64 @llvm.experimental.constrained.fptoui.i64.f64(double %x, metadata !"fpexcept.strict") #0 | ||
ret i64 %result | ||
} | ||
|
||
define i8 @f20s8(double %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: f20s8 | ||
; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) | ||
; CHECK: [[COPY:%[0-9]+]]:gr32_abcd = COPY [[CVTTSD2SIrm]] | ||
; CHECK: [[COPY1:%[0-9]+]]:gr8 = COPY [[COPY]].sub_8bit | ||
; CHECK: $al = COPY [[COPY1]] | ||
; CHECK: RET 0, $al | ||
%result = call i8 @llvm.experimental.constrained.fptosi.i8.f64(double %x, metadata !"fpexcept.strict") #0 | ||
ret i8 %result | ||
} | ||
|
||
define i16 @f20s16(double %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: f20s16 | ||
; CHECK: [[CVTTSD2SIrm:%[0-9]+]]:gr32 = CVTTSD2SIrm %fixed-stack.0, 1, $noreg, 0, $noreg, implicit $mxcsr :: (load 8 from %fixed-stack.0, align 16) | ||
; CHECK: [[COPY:%[0-9]+]]:gr16 = COPY [[CVTTSD2SIrm]].sub_16bit | ||
; CHECK: $ax = COPY [[COPY]] | ||
; CHECK: RET 0, $ax | ||
%result = call i16 @llvm.experimental.constrained.fptosi.i16.f64(double %x, metadata !"fpexcept.strict") #0 | ||
ret i16 %result | ||
} | ||
|
||
define i32 @f20u(double %x) #0 { | ||
entry: | ||
; CHECK-LABEL: name: f20u | ||
; CHECK: [[MOVSDrm_alt:%[0-9]+]]:fr64 = MOVSDrm_alt %fixed-stack.0, 1, $noreg, 0, $noreg :: (load 8 from %fixed-stack.0, align 16) | ||
; CHECK: [[MOVSDrm_alt1:%[0-9]+]]:fr64 = MOVSDrm_alt $noreg, 1, $noreg, %const.0, $noreg :: (load 8 from constant-pool) | ||
; CHECK: UCOMISDrr [[MOVSDrm_alt1]], [[MOVSDrm_alt]], implicit-def $eflags, implicit $mxcsr | ||
; CHECK: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 6, implicit $eflags | ||
; CHECK: [[MOVZX32rr8_:%[0-9]+]]:gr32 = MOVZX32rr8 killed [[SETCCr]] | ||
; CHECK: [[SHL32ri:%[0-9]+]]:gr32 = SHL32ri [[MOVZX32rr8_]], 31, implicit-def dead $eflags | ||
; CHECK: [[CMPSDrr:%[0-9]+]]:fr64 = CMPSDrr [[MOVSDrm_alt]], [[MOVSDrm_alt1]], 1, implicit $mxcsr | ||
; CHECK: [[COPY:%[0-9]+]]:vr128 = COPY [[CMPSDrr]] | ||
; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[MOVSDrm_alt1]] | ||
; CHECK: [[PANDNrr:%[0-9]+]]:vr128 = PANDNrr [[COPY]], killed [[COPY1]] | ||
; CHECK: [[COPY2:%[0-9]+]]:fr64 = COPY [[PANDNrr]] | ||
; CHECK: [[SUBSDrr:%[0-9]+]]:fr64 = SUBSDrr [[MOVSDrm_alt]], killed [[COPY2]], implicit $mxcsr | ||
; CHECK: [[CVTTSD2SIrr:%[0-9]+]]:gr32 = CVTTSD2SIrr killed [[SUBSDrr]], implicit $mxcsr | ||
; CHECK: [[XOR32rr:%[0-9]+]]:gr32 = XOR32rr [[CVTTSD2SIrr]], killed [[SHL32ri]], implicit-def dead $eflags | ||
; CHECK: $eax = COPY [[XOR32rr]] | ||
; CHECK: RET 0, $eax | ||
%result = call i32 @llvm.experimental.constrained.fptoui.i32.f64(double %x, metadata !"fpexcept.strict") #0 | ||
ret i32 %result | ||
} | ||
|
||
attributes #0 = { strictfp } | ||
|
||
declare double @llvm.experimental.constrained.sitofp.f64.i8(i8, metadata, metadata) | ||
declare double @llvm.experimental.constrained.sitofp.f64.i16(i16, metadata, metadata) | ||
declare i32 @llvm.experimental.constrained.fptoui.i32.f64(double, metadata) | ||
declare i64 @llvm.experimental.constrained.fptoui.i64.f64(double, metadata) | ||
declare i8 @llvm.experimental.constrained.fptosi.i8.f64(double, metadata) | ||
declare i16 @llvm.experimental.constrained.fptosi.i16.f64(double, metadata) |
59 changes: 59 additions & 0 deletions
59
llvm/test/CodeGen/X86/vector-constrained-fp-intrinsics-flags.ll
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
; RUN: llc -O3 -mtriple=x86_64-pc-linux -stop-after=finalize-isel < %s | FileCheck %s | ||
|
||
define <1 x float> @constrained_vector_fadd_v1f32() #0 { | ||
; CHECK-LABEL: name: constrained_vector_fadd_v1f32 | ||
; CHECK: [[MOVSSrm_alt:%[0-9]+]]:fr32 = MOVSSrm_alt $rip, 1, $noreg, %const.0, $noreg :: (load 4 from constant-pool) | ||
; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) | ||
; CHECK: $xmm0 = COPY [[ADDSSrm]] | ||
; CHECK: RET 0, $xmm0 | ||
entry: | ||
%add = call <1 x float> @llvm.experimental.constrained.fadd.v1f32(<1 x float> <float 0x7FF0000000000000>, <1 x float> <float 1.0>, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 | ||
ret <1 x float> %add | ||
} | ||
|
||
define <3 x float> @constrained_vector_fadd_v3f32() #0 { | ||
; CHECK-LABEL: name: constrained_vector_fadd_v3f32 | ||
; CHECK: [[FsFLD0SS:%[0-9]+]]:fr32 = FsFLD0SS | ||
; CHECK: [[MOVSSrm_alt:%[0-9]+]]:fr32 = MOVSSrm_alt $rip, 1, $noreg, %const.0, $noreg :: (load 4 from constant-pool) | ||
; CHECK: [[ADDSSrr:%[0-9]+]]:fr32 = ADDSSrr [[MOVSSrm_alt]], killed [[FsFLD0SS]], implicit $mxcsr | ||
; CHECK: [[ADDSSrm:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 4 from constant-pool) | ||
; CHECK: [[ADDSSrm1:%[0-9]+]]:fr32 = ADDSSrm [[MOVSSrm_alt]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 4 from constant-pool) | ||
; CHECK: [[COPY:%[0-9]+]]:vr128 = COPY [[ADDSSrm1]] | ||
; CHECK: [[COPY1:%[0-9]+]]:vr128 = COPY [[ADDSSrm]] | ||
; CHECK: [[UNPCKLPSrr:%[0-9]+]]:vr128 = UNPCKLPSrr [[COPY1]], killed [[COPY]] | ||
; CHECK: [[COPY2:%[0-9]+]]:vr128 = COPY [[ADDSSrr]] | ||
; CHECK: [[UNPCKLPDrr:%[0-9]+]]:vr128 = UNPCKLPDrr [[UNPCKLPSrr]], killed [[COPY2]] | ||
; CHECK: $xmm0 = COPY [[UNPCKLPDrr]] | ||
; CHECK: RET 0, $xmm0 | ||
entry: | ||
%add = call <3 x float> @llvm.experimental.constrained.fadd.v3f32( | ||
<3 x float> <float 0xFFFFFFFFE0000000, float 0xFFFFFFFFE0000000, | ||
float 0xFFFFFFFFE0000000>, | ||
<3 x float> <float 2.0, float 1.0, float 0.0>, | ||
metadata !"round.dynamic", | ||
metadata !"fpexcept.strict") #0 | ||
ret <3 x float> %add | ||
} | ||
|
||
define <4 x double> @constrained_vector_fadd_v4f64() #0 { | ||
; CHECK-LABEL: name: constrained_vector_fadd_v4f64 | ||
; CHECK: [[MOVAPDrm:%[0-9]+]]:vr128 = MOVAPDrm $rip, 1, $noreg, %const.0, $noreg :: (load 16 from constant-pool) | ||
; CHECK: [[ADDPDrm:%[0-9]+]]:vr128 = ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.1, $noreg, implicit $mxcsr :: (load 16 from constant-pool) | ||
; CHECK: [[ADDPDrm1:%[0-9]+]]:vr128 = ADDPDrm [[MOVAPDrm]], $rip, 1, $noreg, %const.2, $noreg, implicit $mxcsr :: (load 16 from constant-pool) | ||
; CHECK: $xmm0 = COPY [[ADDPDrm]] | ||
; CHECK: $xmm1 = COPY [[ADDPDrm1]] | ||
; CHECK: RET 0, $xmm0, $xmm1 | ||
entry: | ||
%add = call <4 x double> @llvm.experimental.constrained.fadd.v4f64( | ||
<4 x double> <double 0x7FEFFFFFFFFFFFFF, double 0x7FEFFFFFFFFFFFFF, | ||
double 0x7FEFFFFFFFFFFFFF, double 0x7FEFFFFFFFFFFFFF>, | ||
<4 x double> <double 1.000000e+00, double 1.000000e-01, | ||
double 2.000000e+00, double 2.000000e-01>, | ||
metadata !"round.dynamic", | ||
metadata !"fpexcept.strict") #0 | ||
ret <4 x double> %add | ||
} | ||
|
||
declare <1 x float> @llvm.experimental.constrained.fadd.v1f32(<1 x float>, <1 x float>, metadata, metadata) | ||
declare <3 x float> @llvm.experimental.constrained.fadd.v3f32(<3 x float>, <3 x float>, metadata, metadata) | ||
declare <4 x double> @llvm.experimental.constrained.fadd.v4f64(<4 x double>, <4 x double>, metadata, metadata) |