1*1364750dSJames Henderson // RUN: %dexter --fail-lt 1.0 -w \
2*1364750dSJames Henderson // RUN: --builder 'clang' --debugger 'lldb' \
3*1364750dSJames Henderson // RUN: --cflags "-ffast-math -O2 -g" -- %s
4*1364750dSJames Henderson // RUN: %dexter --fail-lt 1.0 -w \
5*1364750dSJames Henderson // RUN: --builder 'clang' --debugger 'lldb' \
6*1364750dSJames Henderson // RUN: --cflags "-ffast-math -O0 -g" -- %s
7*1364750dSJames Henderson
8*1364750dSJames Henderson // REQUIRES: lldb
9*1364750dSJames Henderson // UNSUPPORTED: system-windows
10*1364750dSJames Henderson
11*1364750dSJames Henderson //// Check that the debugging experience with __attribute__((optnone)) at O2
12*1364750dSJames Henderson //// matches O0. Test scalar floating point arithmetic with -ffast-math.
13*1364750dSJames Henderson
14*1364750dSJames Henderson //// Example of strength reduction.
15*1364750dSJames Henderson //// The division by 10.0f can be rewritten as a multiply by 0.1f.
16*1364750dSJames Henderson //// A / 10.f ==> A * 0.1f
17*1364750dSJames Henderson //// This is safe with fastmath since we treat the two operations
18*1364750dSJames Henderson //// as equally precise. However we don't want this to happen
19*1364750dSJames Henderson //// with optnone.
20*1364750dSJames Henderson __attribute__((optnone))
test_fdiv(float A)21*1364750dSJames Henderson float test_fdiv(float A) {
22*1364750dSJames Henderson float result;
23*1364750dSJames Henderson result = A / 10.f; // DexLabel('fdiv_assign')
24*1364750dSJames Henderson return result; // DexLabel('fdiv_ret')
25*1364750dSJames Henderson }
26*1364750dSJames Henderson // DexExpectWatchValue('A', 4, on_line=ref('fdiv_assign'))
27*1364750dSJames Henderson // DexExpectWatchValue('result', '0.400000006', on_line=ref('fdiv_ret'))
28*1364750dSJames Henderson
29*1364750dSJames Henderson //// (A * B) - (A * C) ==> A * (B - C)
30*1364750dSJames Henderson __attribute__((optnone))
test_distributivity(float A,float B,float C)31*1364750dSJames Henderson float test_distributivity(float A, float B, float C) {
32*1364750dSJames Henderson float result;
33*1364750dSJames Henderson float op1 = A * B;
34*1364750dSJames Henderson float op2 = A * C; // DexLabel('distributivity_op2')
35*1364750dSJames Henderson result = op1 - op2; // DexLabel('distributivity_result')
36*1364750dSJames Henderson return result; // DexLabel('distributivity_ret')
37*1364750dSJames Henderson }
38*1364750dSJames Henderson // DexExpectWatchValue('op1', '20', on_line=ref('distributivity_op2'))
39*1364750dSJames Henderson // DexExpectWatchValue('op2', '24', on_line=ref('distributivity_result'))
40*1364750dSJames Henderson // DexExpectWatchValue('result', '-4', on_line=ref('distributivity_ret'))
41*1364750dSJames Henderson
42*1364750dSJames Henderson //// (A + B) + C == A + (B + C)
43*1364750dSJames Henderson //// therefore, ((A + B) + C) + (A + (B + C)))
44*1364750dSJames Henderson //// can be rewritten as
45*1364750dSJames Henderson //// 2.0f * ((A + B) + C)
46*1364750dSJames Henderson //// Clang is currently unable to spot this optimization
47*1364750dSJames Henderson //// opportunity with fastmath.
48*1364750dSJames Henderson __attribute__((optnone))
test_associativity(float A,float B,float C)49*1364750dSJames Henderson float test_associativity(float A, float B, float C) {
50*1364750dSJames Henderson float result;
51*1364750dSJames Henderson float op1 = A + B;
52*1364750dSJames Henderson float op2 = B + C;
53*1364750dSJames Henderson op1 += C; // DexLabel('associativity_op1')
54*1364750dSJames Henderson op2 += A;
55*1364750dSJames Henderson result = op1 + op2; // DexLabel('associativity_result')
56*1364750dSJames Henderson return result; // DexLabel('associativity_ret')
57*1364750dSJames Henderson }
58*1364750dSJames Henderson // DexExpectWatchValue('op1', '9', '15', from_line=ref('associativity_op1'), to_line=ref('associativity_result'))
59*1364750dSJames Henderson // DexExpectWatchValue('op2', '11', '15', from_line=ref('associativity_op1'), to_line=ref('associativity_result'))
60*1364750dSJames Henderson // DexExpectWatchValue('result', '30', on_line=ref('associativity_ret'))
61*1364750dSJames Henderson
62*1364750dSJames Henderson //// With fastmath, the ordering of instructions doesn't matter
63*1364750dSJames Henderson //// since we work under the assumption that there is no loss
64*1364750dSJames Henderson //// in precision. This simplifies things for the optimizer which
65*1364750dSJames Henderson //// can then decide to reorder instructions and fold
66*1364750dSJames Henderson //// redundant operations like this:
67*1364750dSJames Henderson //// A += 5.0f
68*1364750dSJames Henderson //// A -= 5.0f
69*1364750dSJames Henderson //// -->
70*1364750dSJames Henderson //// A
71*1364750dSJames Henderson //// This function can be simplified to a return A + B.
72*1364750dSJames Henderson __attribute__((optnone))
test_simplify_fp_operations(float A,float B)73*1364750dSJames Henderson float test_simplify_fp_operations(float A, float B) {
74*1364750dSJames Henderson float result = A + 10.0f; // DexLabel('fp_operations_result')
75*1364750dSJames Henderson result += B; // DexLabel('fp_operations_add')
76*1364750dSJames Henderson result -= 10.0f;
77*1364750dSJames Henderson return result; // DexLabel('fp_operations_ret')
78*1364750dSJames Henderson }
79*1364750dSJames Henderson // DexExpectWatchValue('A', '8.25', on_line=ref('fp_operations_result'))
80*1364750dSJames Henderson // DexExpectWatchValue('B', '26.3999996', on_line=ref('fp_operations_result'))
81*1364750dSJames Henderson // DexExpectWatchValue('result', '18.25', '44.6500015', '34.6500015', from_line=ref('fp_operations_add'), to_line=ref('fp_operations_ret'))
82*1364750dSJames Henderson
83*1364750dSJames Henderson //// Again, this is a simple return A + B.
84*1364750dSJames Henderson //// Clang is unable to spot the opportunity to fold the code sequence.
85*1364750dSJames Henderson __attribute__((optnone))
test_simplify_fp_operations_2(float A,float B,float C)86*1364750dSJames Henderson float test_simplify_fp_operations_2(float A, float B, float C) {
87*1364750dSJames Henderson float result = A + C; // DexLabel('fp_operations_2_result')
88*1364750dSJames Henderson result += B;
89*1364750dSJames Henderson result -= C; // DexLabel('fp_operations_2_subtract')
90*1364750dSJames Henderson return result; // DexLabel('fp_operations_2_ret')
91*1364750dSJames Henderson }
92*1364750dSJames Henderson // DexExpectWatchValue('A', '9.11999988', on_line=ref('fp_operations_2_result'))
93*1364750dSJames Henderson // DexExpectWatchValue('B', '61.050003', on_line=ref('fp_operations_2_result'))
94*1364750dSJames Henderson // DexExpectWatchValue('C', '1002.11102', on_line=ref('fp_operations_2_result'))
95*1364750dSJames Henderson // DexExpectWatchValue('result', '1072.28101', '70.1699829', from_line=ref('fp_operations_2_subtract'), to_line=ref('fp_operations_2_ret'))
96*1364750dSJames Henderson
main()97*1364750dSJames Henderson int main() {
98*1364750dSJames Henderson float result = test_fdiv(4.0f);
99*1364750dSJames Henderson result += test_distributivity(4.0f, 5.0f, 6.0f);
100*1364750dSJames Henderson result += test_associativity(4.0f, 5.0f, 6.0f);
101*1364750dSJames Henderson result += test_simplify_fp_operations(8.25, result);
102*1364750dSJames Henderson result += test_simplify_fp_operations_2(9.12, result, 1002.111);
103*1364750dSJames Henderson return static_cast<int>(result);
104*1364750dSJames Henderson }
105