130 lines
4.1 KiB
C++
130 lines
4.1 KiB
C++
// RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,DEFAULT %s
|
|
// RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -freciprocal-math -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,FLAG %s
|
|
|
|
float base(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z4basefff
|
|
// FLAG: %[[A:.+]] = fdiv arcp float %b, %c
|
|
// FLAG: %[[M:.+]] = fdiv arcp float %[[A]], %b
|
|
// FLAG-NEXT: fadd arcp float %[[M]], %c
|
|
|
|
// DEFAULT: %[[A:.+]] = fdiv float %b, %c
|
|
// DEFAULT: %[[M:.+]] = fdiv float %[[A]], %b
|
|
// DEFAULT-NEXT: fadd float %[[M]], %c
|
|
a = b / c;
|
|
return a / b + c;
|
|
}
|
|
|
|
// Simple case
|
|
float fp_recip_simple(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z15fp_recip_simplefff
|
|
// CHECK: %[[A:.+]] = fdiv arcp float %b, %c
|
|
// CHECK: %[[M:.+]] = fdiv arcp float %[[A]], %b
|
|
// CHECK-NEXT: fadd arcp float %[[M]], %c
|
|
#pragma clang fp reciprocal(on)
|
|
a = b / c;
|
|
return a / b + c;
|
|
}
|
|
|
|
// Test interaction with -freciprocal-math
|
|
float fp_recip_disable(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z16fp_recip_disablefff
|
|
// CHECK: %[[A:.+]] = fdiv float %b, %c
|
|
// CHECK: %[[M:.+]] = fdiv float %[[A]], %b
|
|
// CHECK-NEXT: fadd float %[[M]], %c
|
|
#pragma clang fp reciprocal(off)
|
|
a = b / c;
|
|
return a / b + c;
|
|
}
|
|
|
|
float fp_recip_with_reassoc_simple(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z28fp_recip_with_reassoc_simplefff
|
|
// CHECK: %[[A:.+]] = fmul reassoc arcp float %b, %c
|
|
// CHECK: %[[M:.+]] = fdiv reassoc arcp float %b, %[[A]]
|
|
// CHECK-NEXT: fadd reassoc arcp float %[[M]], %c
|
|
#pragma clang fp reciprocal(on) reassociate(on)
|
|
a = b / c;
|
|
return a / b + c;
|
|
}
|
|
|
|
// arcp pragma should only apply to its scope
|
|
float fp_recip_scoped(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z15fp_recip_scopedfff
|
|
// DEFAULT: %[[M:.+]] = fdiv float %a, %b
|
|
// DEFAULT-NEXT: fadd float %[[M]], %c
|
|
// FLAG: %[[M:.+]] = fdiv arcp float %a, %b
|
|
// FLAG-NEXT: fadd arcp float %[[M]], %c
|
|
{
|
|
#pragma clang fp reciprocal(on)
|
|
}
|
|
return a / b + c;
|
|
}
|
|
|
|
// arcp pragma should apply to templates as well
|
|
class Foo {};
|
|
Foo operator+(Foo, Foo);
|
|
template <typename T>
|
|
T template_recip(T a, T b, T c) {
|
|
#pragma clang fp reciprocal(on)
|
|
return ((a / b) - c) + c;
|
|
}
|
|
|
|
float fp_recip_template(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z17fp_recip_templatefff
|
|
// CHECK: %[[A1:.+]] = fdiv arcp float %a, %b
|
|
// CHECK-NEXT: %[[A2:.+]] = fsub arcp float %[[A1]], %c
|
|
// CHECK-NEXT: fadd arcp float %[[A2]], %c
|
|
return template_recip<float>(a, b, c);
|
|
}
|
|
|
|
// File Scoping should work across functions
|
|
#pragma clang fp reciprocal(on)
|
|
float fp_file_scope_on(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z16fp_file_scope_onfff
|
|
// CHECK: %[[M1:.+]] = fdiv arcp float %a, %c
|
|
// CHECK-NEXT: %[[M2:.+]] = fdiv arcp float %b, %c
|
|
// CHECK-NEXT: fadd arcp float %[[M1]], %[[M2]]
|
|
return (a / c) + (b / c);
|
|
}
|
|
|
|
// Inner pragma has precedence
|
|
float fp_file_scope_stop(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z18fp_file_scope_stopfff
|
|
// CHECK: %[[A:.+]] = fdiv arcp float %a, %a
|
|
// CHECK: %[[M1:.+]] = fdiv float %[[A]], %c
|
|
// CHECK-NEXT: %[[M2:.+]] = fdiv float %b, %c
|
|
// CHECK-NEXT: fsub float %[[M1]], %[[M2]]
|
|
a = a / a;
|
|
{
|
|
#pragma clang fp reciprocal(off)
|
|
return (a / c) - (b / c);
|
|
}
|
|
}
|
|
|
|
#pragma clang fp reciprocal(off)
|
|
float fp_recip_off(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z12fp_recip_offfff
|
|
// CHECK: %[[D1:.+]] = fdiv float %a, %c
|
|
// CHECK-NEXT: %[[D2:.+]] = fdiv float %b, %c
|
|
// CHECK-NEXT: fadd float %[[D1]], %[[D2]]
|
|
return (a / c) + (b / c);
|
|
}
|
|
|
|
// Takes latest flag
|
|
float fp_recip_many(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z13fp_recip_manyfff
|
|
// CHECK: %[[D1:.+]] = fdiv arcp float %a, %c
|
|
// CHECK-NEXT: %[[D2:.+]] = fdiv arcp float %b, %c
|
|
// CHECK-NEXT: fadd arcp float %[[D1]], %[[D2]]
|
|
#pragma clang fp reciprocal(off) reciprocal(on)
|
|
return (a / c) + (b / c);
|
|
}
|
|
|
|
// Pragma does not propagate through called functions
|
|
float helper_func(float a, float b, float c) { return a + b + c; }
|
|
float fp_recip_call_helper(float a, float b, float c) {
|
|
// CHECK-LABEL: _Z20fp_recip_call_helperfff
|
|
// CHECK: %[[S1:.+]] = fadd float %a, %b
|
|
// CHECK-NEXT: fadd float %[[S1]], %c
|
|
#pragma clang fp reciprocal(on)
|
|
return helper_func(a, b, c);
|
|
}
|