1 // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,DEFAULT %s 2 // RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -freciprocal-math -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,FLAG %s 3 4 float base(float a, float b, float c) { 5 // CHECK-LABEL: _Z4basefff 6 // FLAG: %[[A:.+]] = fdiv arcp float %b, %c 7 // FLAG: %[[M:.+]] = fdiv arcp float %[[A]], %b 8 // FLAG-NEXT: fadd arcp float %c, %[[M]] 9 10 // DEFAULT: %[[A:.+]] = fdiv float %b, %c 11 // DEFAULT: %[[M:.+]] = fdiv float %[[A]], %b 12 // DEFAULT-NEXT: fadd float %c, %[[M]] 13 a = b / c; 14 return a / b + c; 15 } 16 17 // Simple case 18 float fp_recip_simple(float a, float b, float c) { 19 // CHECK-LABEL: _Z15fp_recip_simplefff 20 // CHECK: %[[A:.+]] = fdiv arcp float %b, %c 21 // CHECK: %[[M:.+]] = fdiv arcp float %[[A]], %b 22 // CHECK-NEXT: fadd arcp float %c, %[[M]] 23 #pragma clang fp reciprocal(on) 24 a = b / c; 25 return a / b + c; 26 } 27 28 // Test interaction with -freciprocal-math 29 float fp_recip_disable(float a, float b, float c) { 30 // CHECK-LABEL: _Z16fp_recip_disablefff 31 // CHECK: %[[A:.+]] = fdiv float %b, %c 32 // CHECK: %[[M:.+]] = fdiv float %[[A]], %b 33 // CHECK-NEXT: fadd float %c, %[[M]] 34 #pragma clang fp reciprocal(off) 35 a = b / c; 36 return a / b + c; 37 } 38 39 float fp_recip_with_reassoc_simple(float a, float b, float c) { 40 // CHECK-LABEL: _Z28fp_recip_with_reassoc_simplefff 41 // CHECK: %[[A:.+]] = fmul reassoc arcp float %b, %c 42 // CHECK: %[[M:.+]] = fdiv reassoc arcp float %b, %[[A]] 43 // CHECK-NEXT: fadd reassoc arcp float %c, %[[M]] 44 #pragma clang fp reciprocal(on) reassociate(on) 45 a = b / c; 46 return a / b + c; 47 } 48 49 // arcp pragma should only apply to its scope 50 float fp_recip_scoped(float a, float b, float c) { 51 // CHECK-LABEL: _Z15fp_recip_scopedfff 52 // DEFAULT: %[[M:.+]] = fdiv float %a, %b 53 // DEFAULT-NEXT: fadd float %[[M]], %c 54 // FLAG: %[[M:.+]] = fdiv arcp float %a, %b 55 // FLAG-NEXT: fadd arcp float %[[M]], %c 56 { 57 #pragma clang fp reciprocal(on) 58 } 59 return a / b + c; 60 } 61 62 // arcp pragma should apply to templates as well 63 class Foo {}; 64 Foo operator+(Foo, Foo); 65 template <typename T> 66 T template_recip(T a, T b, T c) { 67 #pragma clang fp reciprocal(on) 68 return ((a / b) - c) + c; 69 } 70 71 float fp_recip_template(float a, float b, float c) { 72 // CHECK-LABEL: _Z17fp_recip_templatefff 73 // CHECK: %[[A1:.+]] = fdiv arcp float %a, %b 74 // CHECK-NEXT: %[[A2:.+]] = fsub arcp float %[[A1]], %c 75 // CHECK-NEXT: fadd arcp float %c, %[[A2]] 76 return template_recip<float>(a, b, c); 77 } 78 79 // File Scoping should work across functions 80 #pragma clang fp reciprocal(on) 81 float fp_file_scope_on(float a, float b, float c) { 82 // CHECK-LABEL: _Z16fp_file_scope_onfff 83 // CHECK: %[[M1:.+]] = fdiv arcp float %a, %c 84 // CHECK-NEXT: %[[M2:.+]] = fdiv arcp float %b, %c 85 // CHECK-NEXT: fadd arcp float %[[M1]], %[[M2]] 86 return (a / c) + (b / c); 87 } 88 89 // Inner pragma has precedence 90 float fp_file_scope_stop(float a, float b, float c) { 91 // CHECK-LABEL: _Z18fp_file_scope_stopfff 92 // CHECK: %[[A:.+]] = fdiv arcp float %a, %a 93 // CHECK: %[[M1:.+]] = fdiv float %[[A]], %c 94 // CHECK-NEXT: %[[M2:.+]] = fdiv float %b, %c 95 // CHECK-NEXT: fsub float %[[M1]], %[[M2]] 96 a = a / a; 97 { 98 #pragma clang fp reciprocal(off) 99 return (a / c) - (b / c); 100 } 101 } 102 103 #pragma clang fp reciprocal(off) 104 float fp_recip_off(float a, float b, float c) { 105 // CHECK-LABEL: _Z12fp_recip_offfff 106 // CHECK: %[[D1:.+]] = fdiv float %a, %c 107 // CHECK-NEXT: %[[D2:.+]] = fdiv float %b, %c 108 // CHECK-NEXT: fadd float %[[D1]], %[[D2]] 109 return (a / c) + (b / c); 110 } 111 112 // Takes latest flag 113 float fp_recip_many(float a, float b, float c) { 114 // CHECK-LABEL: _Z13fp_recip_manyfff 115 // CHECK: %[[D1:.+]] = fdiv arcp float %a, %c 116 // CHECK-NEXT: %[[D2:.+]] = fdiv arcp float %b, %c 117 // CHECK-NEXT: fadd arcp float %[[D1]], %[[D2]] 118 #pragma clang fp reciprocal(off) reciprocal(on) 119 return (a / c) + (b / c); 120 } 121 122 // Pragma does not propagate through called functions 123 float helper_func(float a, float b, float c) { return a + b + c; } 124 float fp_recip_call_helper(float a, float b, float c) { 125 // CHECK-LABEL: _Z20fp_recip_call_helperfff 126 // CHECK: %[[S1:.+]] = fadd float %a, %b 127 // CHECK-NEXT: fadd float %[[S1]], %c 128 #pragma clang fp reciprocal(on) 129 return helper_func(a, b, c); 130 } 131