| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,111 @@ | ||
| ; RUN: llc -O3 -mtriple=x86_64-pc-linux < %s | FileCheck %s | ||
|
|
||
| ; Verify that constants aren't folded to inexact results when the rounding mode | ||
| ; is unknown. | ||
| ; | ||
| ; double f1() { | ||
| ; // Because 0.1 cannot be represented exactly, this shouldn't be folded. | ||
| ; return 1.0/10.0; | ||
| ; } | ||
| ; | ||
| ; CHECK-LABEL: f1 | ||
| ; CHECK: divsd | ||
| define double @f1() { | ||
| entry: | ||
| %div = call double @llvm.experimental.constrained.fdiv.f64( | ||
| double 1.000000e+00, | ||
| double 1.000000e+01, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %div | ||
| } | ||
|
|
||
| ; Verify that 'a - 0' isn't simplified to 'a' when the rounding mode is unknown. | ||
| ; | ||
| ; double f2(double a) { | ||
| ; // Because the result of '0 - 0' is negative zero if rounding mode is | ||
| ; // downward, this shouldn't be simplified. | ||
| ; return a - 0; | ||
| ; } | ||
| ; | ||
| ; CHECK-LABEL: f2 | ||
| ; CHECK: subsd | ||
| define double @f2(double %a) { | ||
| entry: | ||
| %div = call double @llvm.experimental.constrained.fsub.f64( | ||
| double %a, | ||
| double 0.000000e+00, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %div | ||
| } | ||
|
|
||
| ; Verify that '-((-a)*b)' isn't simplified to 'a*b' when the rounding mode is | ||
| ; unknown. | ||
| ; | ||
| ; double f3(double a, double b) { | ||
| ; // Because the intermediate value involved in this calculation may require | ||
| ; // rounding, this shouldn't be simplified. | ||
| ; return -((-a)*b); | ||
| ; } | ||
| ; | ||
| ; CHECK-LABEL: f3: | ||
| ; CHECK: subsd | ||
| ; CHECK: mulsd | ||
| ; CHECK: subsd | ||
| define double @f3(double %a, double %b) { | ||
| entry: | ||
| %sub = call double @llvm.experimental.constrained.fsub.f64( | ||
| double -0.000000e+00, double %a, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| %mul = call double @llvm.experimental.constrained.fmul.f64( | ||
| double %sub, double %b, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| %ret = call double @llvm.experimental.constrained.fsub.f64( | ||
| double -0.000000e+00, | ||
| double %mul, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %ret | ||
| } | ||
|
|
||
| ; Verify that FP operations are not performed speculatively when FP exceptions | ||
| ; are not being ignored. | ||
| ; | ||
| ; double f4(int n, double a) { | ||
| ; // Because a + 1 may overflow, this should not be simplified. | ||
| ; if (n > 0) | ||
| ; return a + 1.0; | ||
| ; return a; | ||
| ; } | ||
| ; | ||
| ; | ||
| ; CHECK-LABEL: f4: | ||
| ; CHECK: testl | ||
| ; CHECK: jle | ||
| ; CHECK: addsd | ||
| define double @f4(i32 %n, double %a) { | ||
| entry: | ||
| %cmp = icmp sgt i32 %n, 0 | ||
| br i1 %cmp, label %if.then, label %if.end | ||
|
|
||
| if.then: | ||
| %add = call double @llvm.experimental.constrained.fadd.f64( | ||
| double 1.000000e+00, double %a, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| br label %if.end | ||
|
|
||
| if.end: | ||
| %a.0 = phi double [%add, %if.then], [ %a, %entry ] | ||
| ret double %a.0 | ||
| } | ||
|
|
||
|
|
||
| @llvm.fp.env = thread_local global i8 zeroinitializer, section "llvm.metadata" | ||
| declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| ; RUN: opt -O3 -S < %s | FileCheck %s | ||
|
|
||
| ; Test to verify that constants aren't folded when the rounding mode is unknown. | ||
| ; CHECK-LABEL: @f1 | ||
| ; CHECK: call double @llvm.experimental.constrained.fdiv.f64 | ||
| define double @f1() { | ||
| entry: | ||
| %div = call double @llvm.experimental.constrained.fdiv.f64( | ||
| double 1.000000e+00, | ||
| double 1.000000e+01, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %div | ||
| } | ||
|
|
||
| ; Verify that 'a - 0' isn't simplified to 'a' when the rounding mode is unknown. | ||
| ; | ||
| ; double f2(double a) { | ||
| ; // Because the result of '0 - 0' is negative zero if rounding mode is | ||
| ; // downward, this shouldn't be simplified. | ||
| ; return a - 0.0; | ||
| ; } | ||
| ; | ||
| ; CHECK-LABEL: @f2 | ||
| ; CHECK: call double @llvm.experimental.constrained.fsub.f64 | ||
| define double @f2(double %a) { | ||
| entry: | ||
| %div = call double @llvm.experimental.constrained.fsub.f64( | ||
| double %a, double 0.000000e+00, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %div | ||
| } | ||
|
|
||
| ; Verify that '-((-a)*b)' isn't simplified to 'a*b' when the rounding mode is | ||
| ; unknown. | ||
| ; | ||
| ; double f3(double a, double b) { | ||
| ; // Because the intermediate value involved in this calculation may require | ||
| ; // rounding, this shouldn't be simplified. | ||
| ; return -((-a)*b); | ||
| ; } | ||
| ; | ||
| ; CHECK-LABEL: @f3 | ||
| ; CHECK: call double @llvm.experimental.constrained.fsub.f64 | ||
| ; CHECK: call double @llvm.experimental.constrained.fmul.f64 | ||
| ; CHECK: call double @llvm.experimental.constrained.fsub.f64 | ||
| define double @f3(double %a, double %b) { | ||
| entry: | ||
| %sub = call double @llvm.experimental.constrained.fsub.f64( | ||
| double -0.000000e+00, double %a, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| %mul = call double @llvm.experimental.constrained.fmul.f64( | ||
| double %sub, double %b, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| %ret = call double @llvm.experimental.constrained.fsub.f64( | ||
| double -0.000000e+00, | ||
| double %mul, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %ret | ||
| } | ||
|
|
||
| ; Verify that FP operations are not performed speculatively when FP exceptions | ||
| ; are not being ignored. | ||
| ; | ||
| ; double f4(int n, double a) { | ||
| ; // Because a + 1 may overflow, this should not be simplified. | ||
| ; if (n > 0) | ||
| ; return a + 1.0; | ||
| ; return a; | ||
| ; } | ||
| ; | ||
| ; | ||
| ; CHECK-LABEL: @f4 | ||
| ; CHECK-NOT: select | ||
| ; CHECK: br i1 %cmp | ||
| define double @f4(i32 %n, double %a) { | ||
| entry: | ||
| %cmp = icmp sgt i32 %n, 0 | ||
| br i1 %cmp, label %if.then, label %if.end | ||
|
|
||
| if.then: | ||
| %add = call double @llvm.experimental.constrained.fadd.f64( | ||
| double 1.000000e+00, double %a, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| br label %if.end | ||
|
|
||
| if.end: | ||
| %a.0 = phi double [%add, %if.then], [ %a, %entry ] | ||
| ret double %a.0 | ||
| } | ||
|
|
||
|
|
||
| @llvm.fp.env = thread_local global i8 zeroinitializer, section "llvm.metadata" | ||
| declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) | ||
| declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| ; RUN: opt -verify -S < %s 2>&1 | FileCheck --check-prefix=CHECK1 %s | ||
| ; RUN: sed -e s/.T2:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s | ||
| ; RUN: sed -e s/.T3:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s | ||
|
|
||
| ; Common declaration used for all runs. | ||
| declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) | ||
|
|
||
| ; Test that the verifier accepts legal code, and that the correct attributes are | ||
| ; attached to the FP intrinsic. | ||
| ; CHECK1: declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) #[[ATTR:[0-9]+]] | ||
| ; CHECK1: attributes #[[ATTR]] = { inaccessiblememonly nounwind } | ||
| ; Note: FP exceptions aren't usually caught through normal unwind mechanisms, | ||
| ; but we may want to revisit this for asynchronous exception handling. | ||
| define double @f1(double %a, double %b) { | ||
| entry: | ||
| %fadd = call double @llvm.experimental.constrained.fadd.f64( | ||
| double %a, double %b, | ||
| metadata !"round.dynamic", | ||
| metadata !"fpexcept.strict") | ||
| ret double %fadd | ||
| } | ||
|
|
||
| ; Test an illegal value for the rounding mode argument. | ||
| ; CHECK2: invalid rounding mode argument | ||
| ;T2: define double @f2(double %a, double %b) { | ||
| ;T2: entry: | ||
| ;T2: %fadd = call double @llvm.experimental.constrained.fadd.f64( | ||
| ;T2: double %a, double %b, | ||
| ;T2: metadata !"round.dynomite", | ||
| ;T2: metadata !"fpexcept.strict") | ||
| ;T2: ret double %fadd | ||
| ;T2: } | ||
|
|
||
| ; Test an illegal value for the exception behavior argument. | ||
| ; CHECK3: invalid exception behavior argument | ||
| ;T3: define double @f2(double %a, double %b) { | ||
| ;T3: entry: | ||
| ;T3: %fadd = call double @llvm.experimental.constrained.fadd.f64( | ||
| ;T3: double %a, double %b, | ||
| ;T3: metadata !"round.dynamic", | ||
| ;T3: metadata !"fpexcept.restrict") | ||
| ;T3: ret double %fadd | ||
| ;T3: } |