Kevin P. Neal f57fb82e0f [FPEnv][AArch64] Correct strictfp tests.
Correct AArch64 strictfp tests to follow the rules documented in the LangRef:
https://llvm.org/docs/LangRef.html#constrained-floating-point-intrinsics

Mostly these tests just needed the strictfp attribute on function
definitions.  I've also removed the strictfp attribute from uses
of the constrained intrinsics because it comes by default since
D154991, but I only did this in tests I was changing anyway.

I have removed attributes added to declare lines of intrinsics. The
attributes of intrinsics cannot be changed in a test so I eliminated
attempts to do so.

Test changes verified with D146845.
2023-07-26 09:14:25 -04:00

181 lines
6.8 KiB
LLVM

; RUN: llc -mtriple=aarch64 %s -o - | FileCheck %s
; RUN: llc -mtriple=aarch64 -global-isel=true -global-isel-abort=2 %s -o - | FileCheck %s
; Div whose result is unused should be removed unless we have strict exceptions
; CHECK-LABEL: unused_div:
; CHECK-NOT: fdiv
; CHECK: ret
define void @unused_div(float %x, float %y) {
entry:
%add = fdiv float %x, %y
ret void
}
; CHECK-LABEL: unused_div_fpexcept_strict:
; CHECK: fdiv s0, s0, s1
; CHECK-NEXT: ret
define void @unused_div_fpexcept_strict(float %x, float %y) #0 {
entry:
%add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
ret void
}
; CHECK-LABEL: unused_div_round_dynamic:
; CHECK-NOT: fdiv
; CHECK: ret
define void @unused_div_round_dynamic(float %x, float %y) #0 {
entry:
%add = call float @llvm.experimental.constrained.fdiv.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
ret void
}
; Machine CSE should eliminate the second add unless we have strict exceptions
; CHECK-LABEL: add_twice:
; CHECK: fadd [[ADD:s[0-9]+]], s0, s1
; CHECK-NEXT: cmp w0, #0
; CHECK-NEXT: fmul [[MUL:s[0-9]+]], [[ADD]], [[ADD]]
; CHECK-NEXT: fcsel s0, [[ADD]], [[MUL]], eq
; CHECK-NEXT: ret
define float @add_twice(float %x, float %y, i32 %n) {
entry:
%add = fadd float %x, %y
%tobool.not = icmp eq i32 %n, 0
br i1 %tobool.not, label %if.end, label %if.then
if.then:
%add1 = fadd float %x, %y
%mul = fmul float %add, %add1
br label %if.end
if.end:
%a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
ret float %a.0
}
; CHECK-LABEL: add_twice_fpexcept_strict:
; CHECK: fmov [[X:s[0-9]+]], s0
; CHECK-NEXT: fadd s0, s0, s1
; CHECK-NEXT: cbz w0, [[LABEL:.LBB[0-9_]+]]
; CHECK: fadd [[ADD:s[0-9]+]], [[X]], s1
; CHECK-NEXT: fmul s0, s0, [[ADD]]
; CHECK: [[LABEL]]:
; CHECK-NEXT: ret
define float @add_twice_fpexcept_strict(float %x, float %y, i32 %n) #0 {
entry:
%add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
%tobool.not = icmp eq i32 %n, 0
br i1 %tobool.not, label %if.end, label %if.then
if.then:
%add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
%mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
br label %if.end
if.end:
%a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
ret float %a.0
}
; CHECK-LABEL: add_twice_round_dynamic:
; CHECK: fadd s0, s0, s1
; CHECK-NEXT: cbz w0, [[LABEL:.LBB[0-9_]+]]
; CHECK-NOT: fadd
; CHECK: fmul s0, s0, s0
; CHECK: [[LABEL]]:
; CHECK-NEXT: ret
define float @add_twice_round_dynamic(float %x, float %y, i32 %n) #0 {
entry:
%add = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
%tobool.not = icmp eq i32 %n, 0
br i1 %tobool.not, label %if.end, label %if.then
if.then:
%add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
%mul = call float @llvm.experimental.constrained.fmul.f32(float %add, float %add1, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
br label %if.end
if.end:
%a.0 = phi float [ %mul, %if.then ], [ %add, %entry ]
ret float %a.0
}
; Two adds separated by llvm.set.rounding should be preserved when rounding is
; dynamic (as they may give different results) or when we have strict exceptions
; (the llvm.set.rounding is irrelevant, but both could trap).
; CHECK-LABEL: set_rounding:
; CHECK-DAG: fadd [[SREG:s[0-9]+]], s0, s1
; CHECK-DAG: mrs [[XREG1:x[0-9]+]], FPCR
; CHECK-DAG: orr [[XREG2:x[0-9]+]], [[XREG1]], #0xc00000
; CHECK: msr FPCR, [[XREG2]]
; CHECK-NEXT: mrs [[XREG3:x[0-9]+]], FPCR
; CHECK-NEXT: and [[XREG4:x[0-9]+]], [[XREG3]], #0xffffffffff3fffff
; CHECK-NEXT: msr FPCR, [[XREG4]]
; CHECK-NEXT: fsub s0, [[SREG]], [[SREG]]
; CHECK-NEXT: ret
define float @set_rounding(float %x, float %y) {
entry:
%add1 = fadd float %x, %y
call void @llvm.set.rounding(i32 0)
%add2 = fadd float %x, %y
call void @llvm.set.rounding(i32 1)
%sub = fsub float %add1, %add2
ret float %sub
}
; CHECK-LABEL: set_rounding_fpexcept_strict:
; CHECK-DAG: fadd [[SREG1:s[0-9]+]], s0, s1
; CHECK-DAG: mrs [[XREG1:x[0-9]+]], FPCR
; CHECK-DAG: orr [[XREG2:x[0-9]+]], [[XREG1]], #0xc00000
; CHECK: msr FPCR, [[XREG2]]
; CHECK-DAG: fadd [[SREG2:s[0-9]+]], s0, s1
; CHECK-DAG: mrs [[XREG3:x[0-9]+]], FPCR
; CHECK-DAG: and [[XREG4:x[0-9]+]], [[XREG3]], #0xffffffffff3fffff
; CHECK-NEXT: msr FPCR, [[XREG4]]
; CHECK-NEXT: fsub s0, [[SREG1]], [[SREG2]]
; CHECK-NEXT: ret
define float @set_rounding_fpexcept_strict(float %x, float %y) #0 {
entry:
%add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
call void @llvm.set.rounding(i32 0) #0
%add2 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
call void @llvm.set.rounding(i32 1) #0
%sub = call float @llvm.experimental.constrained.fsub.f32(float %add1, float %add2, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
ret float %sub
}
; CHECK-LABEL: set_rounding_round_dynamic:
; CHECK-DAG: fadd [[SREG1:s[0-9]+]], s0, s1
; CHECK-DAG: mrs [[XREG1:x[0-9]+]], FPCR
; CHECK-DAG: orr [[XREG2:x[0-9]+]], [[XREG1]], #0xc00000
; CHECK: msr FPCR, [[XREG2]]
; CHECK-DAG: fadd [[SREG2:s[0-9]+]], s0, s1
; CHECK-DAG: mrs [[XREG3:x[0-9]+]], FPCR
; CHECK-DAG: and [[XREG4:x[0-9]+]], [[XREG3]], #0xffffffffff3fffff
; CHECK-NEXT: msr FPCR, [[XREG4]]
; CHECK-NEXT: fsub s0, [[SREG1]], [[SREG2]]
; CHECK-NEXT: ret
define float @set_rounding_round_dynamic(float %x, float %y) #0 {
entry:
%add1 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
call void @llvm.set.rounding(i32 0) #0
%add2 = call float @llvm.experimental.constrained.fadd.f32(float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
call void @llvm.set.rounding(i32 1) #0
%sub = call float @llvm.experimental.constrained.fsub.f32(float %add1, float %add2, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
ret float %sub
}
declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
declare float @llvm.experimental.constrained.fsub.f32(float, float, metadata, metadata)
declare float @llvm.experimental.constrained.fmul.f32(float, float, metadata, metadata)
declare float @llvm.experimental.constrained.fdiv.f32(float, float, metadata, metadata)
declare i32 @llvm.get.rounding()
declare void @llvm.set.rounding(i32)
attributes #0 = { strictfp }