mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-05 01:20:51 +03:00

Which supports more cmdline options in the meantime than what we have been supporting manually, and should be future-proof, similar to InitTargetOptionsFromCodeGenFlags(). Attributes are only set if explicitly specified in the cmdline (and not already present in the function's existing attributes). This started out as a workaround for not being able to determine whether the user has explicitly set -frame-pointer in the cmdline with LLVM 11, and ended with having to touch more than I wanted. An *enabled* -ffast-math flag (from us, not LLVM) overriding LLVM's -enable-unsafe-fp-math, but e.g. -ffast-math=false NOT overriding was/is one of the quirks.
120 lines
3.4 KiB
D
120 lines
3.4 KiB
D
// Tests inline IR + math optimizations
|
|
|
|
// REQUIRES: target_X86
|
|
|
|
// RUN: %ldc -c -output-ll -of=%t.ll %s && FileCheck %s --check-prefix LLVM < %t.ll
|
|
// RUN: %ldc -mtriple=x86_64-linux-gnu -mattr=+fma -O3 -release -c -output-s -of=%t.s %s && FileCheck %s --check-prefix ASM < %t.s
|
|
|
|
import ldc.attributes;
|
|
import ldc.llvmasm;
|
|
|
|
// Test that internal @inline.ir.*" functions for the inlined IR pieces are always inlined and are not present as a global symbol
|
|
// LLVM-NOT: @inline.ir.
|
|
// LLVM-NOT: alwaysinline
|
|
|
|
|
|
// __ir should inherit the enclosing function attributes, thus preserving the enclosing function attributes after inlining.
|
|
// LLVM-LABEL: define{{.*}} @dot
|
|
// LLVM-SAME: #[[UNSAFEFPMATH:[0-9]+]]
|
|
// ASM-LABEL: dot:
|
|
@llvmAttr("unsafe-fp-math", "true")
|
|
extern (C) double dot(double[] a, double[] b)
|
|
{
|
|
double s = 0;
|
|
|
|
// ASM: vfmadd{{[123][123][123]}}pd
|
|
foreach (size_t i; 0 .. a.length)
|
|
{
|
|
s = __ir!(`%p = fmul fast double %0, %1
|
|
%r = fadd fast double %p, %2
|
|
ret double %r`, double)(a[i], b[i], s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @features
|
|
// LLVM-SAME: #[[FEAT:[0-9]+]]
|
|
@target("fma")
|
|
extern (C) double features(double[] a, double[] b)
|
|
{
|
|
double s = 0;
|
|
foreach (size_t i; 0 .. a.length)
|
|
{
|
|
s = __ir!(`%p = fmul fast double %0, %1
|
|
%r = fadd fast double %p, %2
|
|
ret double %r`, double)(a[i], b[i], s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Test that inline IR works when calling function has special attributes defined for its parameters
|
|
// LLVM-LABEL: define{{.*}} @dot160
|
|
// ASM-LABEL: dot160:
|
|
extern (C) double dot160(double[160] a, double[160] b)
|
|
{
|
|
double s = 0;
|
|
|
|
// ASM-NOT: vfmadd
|
|
foreach (size_t i; 0 .. a.length)
|
|
{
|
|
s = __ir!(`%p = fmul double %0, %1
|
|
%r = fadd double %p, %2
|
|
ret double %r`, double)(a[i], b[i], s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Test inline IR alias defined outside any function
|
|
alias __ir!(`%p = fmul fast double %0, %1
|
|
%r = fadd fast double %p, %2
|
|
ret double %r`,
|
|
double, double, double, double) muladdFast;
|
|
alias __ir!(`%p = fmul double %0, %1
|
|
%r = fadd double %p, %2
|
|
ret double %r`,
|
|
double, double, double, double) muladd;
|
|
|
|
// LLVM-LABEL: define{{.*}} @aliasInlineUnsafe
|
|
// LLVM-SAME: #[[UNSAFEFPMATH]]
|
|
// ASM-LABEL: aliasInlineUnsafe:
|
|
@llvmAttr("unsafe-fp-math", "true")
|
|
extern (C) double aliasInlineUnsafe(double[] a, double[] b)
|
|
{
|
|
double s = 0;
|
|
|
|
// ASM: vfmadd{{[123][123][123]}}pd
|
|
foreach (size_t i; 0 .. a.length)
|
|
{
|
|
s = muladdFast(a[i], b[i], s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// LLVM-LABEL: define{{.*}} @aliasInlineSafe
|
|
// LLVM-SAME: #[[NO_UNSAFEFPMATH:[0-9]+]]
|
|
// ASM-LABEL: aliasInlineSafe:
|
|
extern (C) double aliasInlineSafe(double[] a, double[] b)
|
|
{
|
|
double s = 0;
|
|
|
|
// ASM-NOT: vfmadd{{[123][123][123]}}pd
|
|
foreach (size_t i; 0 .. a.length)
|
|
{
|
|
s = muladd(a[i], b[i], s);
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Make sure an enclosing function's 'noinline' attribute isn't copied to
|
|
// the inlined IR function (having 'alwaysinline') (issue #1711).
|
|
double neverInlinedEnclosingFunction()
|
|
{
|
|
pragma(inline, false);
|
|
return muladd(1.0, 2.0, 3.0);
|
|
}
|
|
|
|
// LLVM: attributes #[[UNSAFEFPMATH]] ={{.*}} "unsafe-fp-math"="true"
|
|
// LLVM: attributes #[[FEAT]] ={{.*}} "target-features"="{{.*}}+fma{{.*}}"
|
|
|
|
// LLVM: attributes #[[NO_UNSAFEFPMATH]] =
|
|
// LLVM-NOT: "unsafe-fp-math"="true"
|