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