1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py 2 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -target-feature +avx512fp16 -o - | FileCheck %s --check-prefixes=AVX 3 // RUN: %clang_cc1 %s -O0 -emit-llvm -triple x86_64-unknown-unknown -o - | FileCheck %s --check-prefixes=X86 4 5 // AVX-LABEL: @add_half_rr( 6 // AVX-NEXT: entry: 7 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 8 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 9 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 10 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 11 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 12 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 13 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 14 // AVX-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] 15 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 16 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 17 // AVX-NEXT: store half [[ADD]], ptr [[RETVAL_REALP]], align 2 18 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 19 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 20 // AVX-NEXT: ret <2 x half> [[TMP2]] 21 // 22 // X86-LABEL: @add_half_rr( 23 // X86-NEXT: entry: 24 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 25 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 26 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 27 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 28 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 29 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 30 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 31 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 32 // X86-NEXT: [[EXT1:%.*]] = fpext half [[TMP1]] to float 33 // X86-NEXT: [[ADD:%.*]] = fadd float [[EXT]], [[EXT1]] 34 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD]] to half 35 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 36 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 37 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 38 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 39 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 40 // X86-NEXT: ret <2 x half> [[TMP2]] 41 // 42 _Float16 _Complex add_half_rr(_Float16 a, _Float16 b) { 43 return a + b; 44 } 45 46 // AVX-LABEL: @add_half_cr( 47 // AVX-NEXT: entry: 48 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 49 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 50 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 51 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 52 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 53 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 54 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 55 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 56 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 57 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 58 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[TMP0]] 59 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 60 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 61 // AVX-NEXT: store half [[ADD_R]], ptr [[RETVAL_REALP]], align 2 62 // AVX-NEXT: store half [[A_IMAG]], ptr [[RETVAL_IMAGP]], align 2 63 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 64 // AVX-NEXT: ret <2 x half> [[TMP1]] 65 // 66 // X86-LABEL: @add_half_cr( 67 // X86-NEXT: entry: 68 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 69 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 70 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 71 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 72 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 73 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 74 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 75 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 76 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 77 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 78 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 79 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 80 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 81 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 82 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R]] to half 83 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[EXT1]] to half 84 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 85 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 86 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 87 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 88 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 89 // X86-NEXT: ret <2 x half> [[TMP1]] 90 // 91 _Float16 _Complex add_half_cr(_Float16 _Complex a, _Float16 b) { 92 return a + b; 93 } 94 95 // AVX-LABEL: @add_half_rc( 96 // AVX-NEXT: entry: 97 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 98 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 99 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 100 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 101 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 102 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 103 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 104 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 105 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 106 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 107 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[TMP0]], [[B_REAL]] 108 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 109 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 110 // AVX-NEXT: store half [[ADD_R]], ptr [[RETVAL_REALP]], align 2 111 // AVX-NEXT: store half [[B_IMAG]], ptr [[RETVAL_IMAGP]], align 2 112 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 113 // AVX-NEXT: ret <2 x half> [[TMP1]] 114 // 115 // X86-LABEL: @add_half_rc( 116 // X86-NEXT: entry: 117 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 118 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 119 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 120 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 121 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 122 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 123 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 124 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 125 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 126 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 127 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 128 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 129 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 130 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT1]] 131 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R]] to half 132 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[EXT2]] to half 133 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 134 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 135 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 136 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 137 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 138 // X86-NEXT: ret <2 x half> [[TMP1]] 139 // 140 _Float16 _Complex add_half_rc(_Float16 a, _Float16 _Complex b) { 141 return a + b; 142 } 143 144 // AVX-LABEL: @add_half_cc( 145 // AVX-NEXT: entry: 146 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 147 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 148 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 149 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 150 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 151 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 152 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 153 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 154 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 155 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 156 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 157 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 158 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 159 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[B_REAL]] 160 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[A_IMAG]], [[B_IMAG]] 161 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 162 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 163 // AVX-NEXT: store half [[ADD_R]], ptr [[RETVAL_REALP]], align 2 164 // AVX-NEXT: store half [[ADD_I]], ptr [[RETVAL_IMAGP]], align 2 165 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 166 // AVX-NEXT: ret <2 x half> [[TMP0]] 167 // 168 // X86-LABEL: @add_half_cc( 169 // X86-NEXT: entry: 170 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 171 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 172 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 173 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 174 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 175 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 176 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 177 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 178 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 179 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 180 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 181 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 182 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 183 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 184 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 185 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 186 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 187 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 188 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT1]], [[EXT3]] 189 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R]] to half 190 // X86-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[ADD_I]] to half 191 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 192 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 193 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 194 // X86-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 195 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 196 // X86-NEXT: ret <2 x half> [[TMP0]] 197 // 198 _Float16 _Complex add_half_cc(_Float16 _Complex a, _Float16 _Complex b) { 199 return a + b; 200 } 201 202 // AVX-LABEL: @add2_haff_rrr( 203 // AVX-NEXT: entry: 204 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 205 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 206 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 207 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 208 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 209 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 210 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 211 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 212 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 213 // AVX-NEXT: [[ADD:%.*]] = fadd half [[TMP0]], [[TMP1]] 214 // AVX-NEXT: [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2 215 // AVX-NEXT: [[ADD1:%.*]] = fadd half [[ADD]], [[TMP2]] 216 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 217 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 218 // AVX-NEXT: store half [[ADD1]], ptr [[RETVAL_REALP]], align 2 219 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 220 // AVX-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 221 // AVX-NEXT: ret <2 x half> [[TMP3]] 222 // 223 // X86-LABEL: @add2_haff_rrr( 224 // X86-NEXT: entry: 225 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 226 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 227 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 228 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 229 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 230 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 231 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 232 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 233 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 234 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 235 // X86-NEXT: [[EXT1:%.*]] = fpext half [[TMP1]] to float 236 // X86-NEXT: [[ADD:%.*]] = fadd float [[EXT]], [[EXT1]] 237 // X86-NEXT: [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2 238 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP2]] to float 239 // X86-NEXT: [[ADD3:%.*]] = fadd float [[ADD]], [[EXT2]] 240 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD3]] to half 241 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 242 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 243 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 244 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 245 // X86-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 246 // X86-NEXT: ret <2 x half> [[TMP3]] 247 // 248 _Float16 _Complex add2_haff_rrr(_Float16 a, _Float16 b, _Float16 c) { 249 return a + b + c; 250 } 251 252 // AVX-LABEL: @add2_haff_rcr( 253 // AVX-NEXT: entry: 254 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 255 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 256 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 257 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 258 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 259 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 260 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 261 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 262 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 263 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 264 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 265 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 266 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[TMP0]], [[B_REAL]] 267 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 268 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[TMP1]] 269 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 270 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 271 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 272 // AVX-NEXT: store half [[B_IMAG]], ptr [[RETVAL_IMAGP]], align 2 273 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 274 // AVX-NEXT: ret <2 x half> [[TMP2]] 275 // 276 // X86-LABEL: @add2_haff_rcr( 277 // X86-NEXT: entry: 278 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 279 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 280 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 281 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 282 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 283 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 284 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 285 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 286 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 287 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 288 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 289 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 290 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 291 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 292 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 293 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT1]] 294 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 295 // X86-NEXT: [[EXT3:%.*]] = fpext half [[TMP1]] to float 296 // X86-NEXT: [[ADD_R4:%.*]] = fadd float [[ADD_R]], [[EXT3]] 297 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R4]] to half 298 // X86-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[EXT2]] to half 299 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 300 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 301 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 302 // X86-NEXT: store half [[UNPROMOTION5]], ptr [[RETVAL_IMAGP]], align 2 303 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 304 // X86-NEXT: ret <2 x half> [[TMP2]] 305 // 306 _Float16 _Complex add2_haff_rcr(_Float16 a, _Float16 _Complex b, _Float16 c) { 307 return a + b + c; 308 } 309 310 // AVX-LABEL: @add2_haff_rcc( 311 // AVX-NEXT: entry: 312 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 313 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 314 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 315 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 316 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 317 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 318 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 319 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 320 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 321 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 322 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 323 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 324 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[TMP0]], [[B_REAL]] 325 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 326 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 327 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 328 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 329 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[C_REAL]] 330 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[B_IMAG]], [[C_IMAG]] 331 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 332 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 333 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 334 // AVX-NEXT: store half [[ADD_I]], ptr [[RETVAL_IMAGP]], align 2 335 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 336 // AVX-NEXT: ret <2 x half> [[TMP1]] 337 // 338 // X86-LABEL: @add2_haff_rcc( 339 // X86-NEXT: entry: 340 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 341 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 342 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 343 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 344 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 345 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 346 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 347 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 348 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 349 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 350 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 351 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 352 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 353 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 354 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 355 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT1]] 356 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 357 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 358 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 359 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 360 // X86-NEXT: [[EXT3:%.*]] = fpext half [[C_REAL]] to float 361 // X86-NEXT: [[EXT4:%.*]] = fpext half [[C_IMAG]] to float 362 // X86-NEXT: [[ADD_R5:%.*]] = fadd float [[ADD_R]], [[EXT3]] 363 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT2]], [[EXT4]] 364 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R5]] to half 365 // X86-NEXT: [[UNPROMOTION6:%.*]] = fptrunc float [[ADD_I]] to half 366 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 367 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 368 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 369 // X86-NEXT: store half [[UNPROMOTION6]], ptr [[RETVAL_IMAGP]], align 2 370 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 371 // X86-NEXT: ret <2 x half> [[TMP1]] 372 // 373 _Float16 _Complex add2_haff_rcc(_Float16 a, _Float16 _Complex b, _Float16 _Complex c) { 374 return a + b + c; 375 } 376 377 // AVX-LABEL: @add2_haff_crr( 378 // AVX-NEXT: entry: 379 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 380 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 381 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 382 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 383 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 384 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 385 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 386 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 387 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 388 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 389 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 390 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 391 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[TMP0]] 392 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 393 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[TMP1]] 394 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 395 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 396 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 397 // AVX-NEXT: store half [[A_IMAG]], ptr [[RETVAL_IMAGP]], align 2 398 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 399 // AVX-NEXT: ret <2 x half> [[TMP2]] 400 // 401 // X86-LABEL: @add2_haff_crr( 402 // X86-NEXT: entry: 403 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 404 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 405 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 406 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 407 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 408 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 409 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 410 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 411 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 412 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 413 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 414 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 415 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 416 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 417 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 418 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 419 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 420 // X86-NEXT: [[EXT3:%.*]] = fpext half [[TMP1]] to float 421 // X86-NEXT: [[ADD_R4:%.*]] = fadd float [[ADD_R]], [[EXT3]] 422 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R4]] to half 423 // X86-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[EXT1]] to half 424 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 425 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 426 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 427 // X86-NEXT: store half [[UNPROMOTION5]], ptr [[RETVAL_IMAGP]], align 2 428 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 429 // X86-NEXT: ret <2 x half> [[TMP2]] 430 // 431 _Float16 _Complex add2_haff_crr(_Float16 _Complex a, _Float16 b, _Float16 c) { 432 return a + b + c; 433 } 434 435 // AVX-LABEL: @add2_haff_ccr( 436 // AVX-NEXT: entry: 437 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 438 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 439 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 440 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 441 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 442 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 443 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 444 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 445 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 446 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 447 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 448 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 449 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 450 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 451 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 452 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[B_REAL]] 453 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[A_IMAG]], [[B_IMAG]] 454 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[C_ADDR]], align 2 455 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[TMP0]] 456 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 457 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 458 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 459 // AVX-NEXT: store half [[ADD_I]], ptr [[RETVAL_IMAGP]], align 2 460 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 461 // AVX-NEXT: ret <2 x half> [[TMP1]] 462 // 463 // X86-LABEL: @add2_haff_ccr( 464 // X86-NEXT: entry: 465 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 466 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 467 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 468 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 469 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 470 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 471 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 472 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 473 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 474 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 475 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 476 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 477 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 478 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 479 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 480 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 481 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 482 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 483 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 484 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 485 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT1]], [[EXT3]] 486 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[C_ADDR]], align 2 487 // X86-NEXT: [[EXT4:%.*]] = fpext half [[TMP0]] to float 488 // X86-NEXT: [[ADD_R5:%.*]] = fadd float [[ADD_R]], [[EXT4]] 489 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R5]] to half 490 // X86-NEXT: [[UNPROMOTION6:%.*]] = fptrunc float [[ADD_I]] to half 491 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 492 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 493 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 494 // X86-NEXT: store half [[UNPROMOTION6]], ptr [[RETVAL_IMAGP]], align 2 495 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 496 // X86-NEXT: ret <2 x half> [[TMP1]] 497 // 498 _Float16 _Complex add2_haff_ccr(_Float16 _Complex a, _Float16 _Complex b, _Float16 c) { 499 return a + b + c; 500 } 501 502 // AVX-LABEL: @add2_haff_crc( 503 // AVX-NEXT: entry: 504 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 505 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 506 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 507 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 508 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 509 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 510 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 511 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 512 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 513 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 514 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 515 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 516 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[TMP0]] 517 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 518 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 519 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 520 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 521 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[C_REAL]] 522 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[A_IMAG]], [[C_IMAG]] 523 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 524 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 525 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 526 // AVX-NEXT: store half [[ADD_I]], ptr [[RETVAL_IMAGP]], align 2 527 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 528 // AVX-NEXT: ret <2 x half> [[TMP1]] 529 // 530 // X86-LABEL: @add2_haff_crc( 531 // X86-NEXT: entry: 532 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 533 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 534 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 535 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 536 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 537 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 538 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 539 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 540 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 541 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 542 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 543 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 544 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 545 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 546 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 547 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 548 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 549 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 550 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 551 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 552 // X86-NEXT: [[EXT3:%.*]] = fpext half [[C_REAL]] to float 553 // X86-NEXT: [[EXT4:%.*]] = fpext half [[C_IMAG]] to float 554 // X86-NEXT: [[ADD_R5:%.*]] = fadd float [[ADD_R]], [[EXT3]] 555 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT1]], [[EXT4]] 556 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R5]] to half 557 // X86-NEXT: [[UNPROMOTION6:%.*]] = fptrunc float [[ADD_I]] to half 558 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 559 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 560 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 561 // X86-NEXT: store half [[UNPROMOTION6]], ptr [[RETVAL_IMAGP]], align 2 562 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 563 // X86-NEXT: ret <2 x half> [[TMP1]] 564 // 565 _Float16 _Complex add2_haff_crc(_Float16 _Complex a, _Float16 b, _Float16 _Complex c) { 566 return a + b + c; 567 } 568 569 // AVX-LABEL: @add2_haff_ccc( 570 // AVX-NEXT: entry: 571 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 572 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 573 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 574 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 575 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 576 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 577 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 578 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 579 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 580 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 581 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 582 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 583 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 584 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 585 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 586 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[B_REAL]] 587 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[A_IMAG]], [[B_IMAG]] 588 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 589 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 590 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 591 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 592 // AVX-NEXT: [[ADD_R1:%.*]] = fadd half [[ADD_R]], [[C_REAL]] 593 // AVX-NEXT: [[ADD_I2:%.*]] = fadd half [[ADD_I]], [[C_IMAG]] 594 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 595 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 596 // AVX-NEXT: store half [[ADD_R1]], ptr [[RETVAL_REALP]], align 2 597 // AVX-NEXT: store half [[ADD_I2]], ptr [[RETVAL_IMAGP]], align 2 598 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 599 // AVX-NEXT: ret <2 x half> [[TMP0]] 600 // 601 // X86-LABEL: @add2_haff_ccc( 602 // X86-NEXT: entry: 603 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 604 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 605 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 606 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 607 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 608 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 609 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 610 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 611 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 612 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 613 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 614 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 615 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 616 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 617 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 618 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 619 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 620 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 621 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 622 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[EXT2]] 623 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT1]], [[EXT3]] 624 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 625 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 626 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 627 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 628 // X86-NEXT: [[EXT4:%.*]] = fpext half [[C_REAL]] to float 629 // X86-NEXT: [[EXT5:%.*]] = fpext half [[C_IMAG]] to float 630 // X86-NEXT: [[ADD_R6:%.*]] = fadd float [[ADD_R]], [[EXT4]] 631 // X86-NEXT: [[ADD_I7:%.*]] = fadd float [[ADD_I]], [[EXT5]] 632 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R6]] to half 633 // X86-NEXT: [[UNPROMOTION8:%.*]] = fptrunc float [[ADD_I7]] to half 634 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 635 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 636 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 637 // X86-NEXT: store half [[UNPROMOTION8]], ptr [[RETVAL_IMAGP]], align 2 638 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 639 // X86-NEXT: ret <2 x half> [[TMP0]] 640 // 641 _Float16 _Complex add2_haff_ccc(_Float16 _Complex a, _Float16 _Complex b, _Float16 _Complex c) { 642 return a + b + c; 643 } 644 645 // AVX-LABEL: @sub_half_rr( 646 // AVX-NEXT: entry: 647 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 648 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 649 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 650 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 651 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 652 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 653 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 654 // AVX-NEXT: [[SUB:%.*]] = fsub half [[TMP0]], [[TMP1]] 655 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 656 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 657 // AVX-NEXT: store half [[SUB]], ptr [[RETVAL_REALP]], align 2 658 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 659 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 660 // AVX-NEXT: ret <2 x half> [[TMP2]] 661 // 662 // X86-LABEL: @sub_half_rr( 663 // X86-NEXT: entry: 664 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 665 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 666 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 667 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 668 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 669 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 670 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 671 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 672 // X86-NEXT: [[EXT1:%.*]] = fpext half [[TMP1]] to float 673 // X86-NEXT: [[SUB:%.*]] = fsub float [[EXT]], [[EXT1]] 674 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[SUB]] to half 675 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 676 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 677 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 678 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 679 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 680 // X86-NEXT: ret <2 x half> [[TMP2]] 681 // 682 _Float16 _Complex sub_half_rr(_Float16 a, _Float16 b) { 683 return a - b; 684 } 685 686 // AVX-LABEL: @sub_half_cr( 687 // AVX-NEXT: entry: 688 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 689 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 690 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 691 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 692 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 693 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 694 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 695 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 696 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 697 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 698 // AVX-NEXT: [[SUB_R:%.*]] = fsub half [[A_REAL]], [[TMP0]] 699 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 700 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 701 // AVX-NEXT: store half [[SUB_R]], ptr [[RETVAL_REALP]], align 2 702 // AVX-NEXT: store half [[A_IMAG]], ptr [[RETVAL_IMAGP]], align 2 703 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 704 // AVX-NEXT: ret <2 x half> [[TMP1]] 705 // 706 // X86-LABEL: @sub_half_cr( 707 // X86-NEXT: entry: 708 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 709 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 710 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 711 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 712 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 713 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 714 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 715 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 716 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 717 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 718 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 719 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 720 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 721 // X86-NEXT: [[SUB_R:%.*]] = fsub float [[EXT]], [[EXT2]] 722 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[SUB_R]] to half 723 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[EXT1]] to half 724 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 725 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 726 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 727 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 728 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 729 // X86-NEXT: ret <2 x half> [[TMP1]] 730 // 731 _Float16 _Complex sub_half_cr(_Float16 _Complex a, _Float16 b) { 732 return a - b; 733 } 734 735 // AVX-LABEL: @sub_half_rc( 736 // AVX-NEXT: entry: 737 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 738 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 739 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 740 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 741 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 742 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 743 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 744 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 745 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 746 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 747 // AVX-NEXT: [[SUB_R:%.*]] = fsub half [[TMP0]], [[B_REAL]] 748 // AVX-NEXT: [[SUB_I:%.*]] = fneg half [[B_IMAG]] 749 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 750 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 751 // AVX-NEXT: store half [[SUB_R]], ptr [[RETVAL_REALP]], align 2 752 // AVX-NEXT: store half [[SUB_I]], ptr [[RETVAL_IMAGP]], align 2 753 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 754 // AVX-NEXT: ret <2 x half> [[TMP1]] 755 // 756 // X86-LABEL: @sub_half_rc( 757 // X86-NEXT: entry: 758 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 759 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 760 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 761 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 762 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 763 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 764 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 765 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 766 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 767 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 768 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 769 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 770 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 771 // X86-NEXT: [[SUB_R:%.*]] = fsub float [[EXT]], [[EXT1]] 772 // X86-NEXT: [[SUB_I:%.*]] = fneg float [[EXT2]] 773 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[SUB_R]] to half 774 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[SUB_I]] to half 775 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 776 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 777 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 778 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 779 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 780 // X86-NEXT: ret <2 x half> [[TMP1]] 781 // 782 _Float16 _Complex sub_half_rc(_Float16 a, _Float16 _Complex b) { 783 return a - b; 784 } 785 786 // AVX-LABEL: @sub_half_cc( 787 // AVX-NEXT: entry: 788 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 789 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 790 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 791 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 792 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 793 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 794 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 795 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 796 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 797 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 798 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 799 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 800 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 801 // AVX-NEXT: [[SUB_R:%.*]] = fsub half [[A_REAL]], [[B_REAL]] 802 // AVX-NEXT: [[SUB_I:%.*]] = fsub half [[A_IMAG]], [[B_IMAG]] 803 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 804 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 805 // AVX-NEXT: store half [[SUB_R]], ptr [[RETVAL_REALP]], align 2 806 // AVX-NEXT: store half [[SUB_I]], ptr [[RETVAL_IMAGP]], align 2 807 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 808 // AVX-NEXT: ret <2 x half> [[TMP0]] 809 // 810 // X86-LABEL: @sub_half_cc( 811 // X86-NEXT: entry: 812 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 813 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 814 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 815 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 816 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 817 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 818 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 819 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 820 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 821 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 822 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 823 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 824 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 825 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 826 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 827 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 828 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 829 // X86-NEXT: [[SUB_R:%.*]] = fsub float [[EXT]], [[EXT2]] 830 // X86-NEXT: [[SUB_I:%.*]] = fsub float [[EXT1]], [[EXT3]] 831 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[SUB_R]] to half 832 // X86-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[SUB_I]] to half 833 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 834 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 835 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 836 // X86-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 837 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 838 // X86-NEXT: ret <2 x half> [[TMP0]] 839 // 840 _Float16 _Complex sub_half_cc(_Float16 _Complex a, _Float16 _Complex b) { 841 return a - b; 842 } 843 844 // AVX-LABEL: @mul_half_rr( 845 // AVX-NEXT: entry: 846 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 847 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 848 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 849 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 850 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 851 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 852 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 853 // AVX-NEXT: [[MUL:%.*]] = fmul half [[TMP0]], [[TMP1]] 854 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 855 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 856 // AVX-NEXT: store half [[MUL]], ptr [[RETVAL_REALP]], align 2 857 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 858 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 859 // AVX-NEXT: ret <2 x half> [[TMP2]] 860 // 861 // X86-LABEL: @mul_half_rr( 862 // X86-NEXT: entry: 863 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 864 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 865 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 866 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 867 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 868 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 869 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 870 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 871 // X86-NEXT: [[EXT1:%.*]] = fpext half [[TMP1]] to float 872 // X86-NEXT: [[MUL:%.*]] = fmul float [[EXT]], [[EXT1]] 873 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL]] to half 874 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 875 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 876 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 877 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 878 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 879 // X86-NEXT: ret <2 x half> [[TMP2]] 880 // 881 _Float16 _Complex mul_half_rr(_Float16 a, _Float16 b) { 882 return a * b; 883 } 884 885 // AVX-LABEL: @mul_half_cr( 886 // AVX-NEXT: entry: 887 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 888 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 889 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 890 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 891 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 892 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 893 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 894 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 895 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 896 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 897 // AVX-NEXT: [[MUL_RL:%.*]] = fmul half [[A_REAL]], [[TMP0]] 898 // AVX-NEXT: [[MUL_IL:%.*]] = fmul half [[A_IMAG]], [[TMP0]] 899 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 900 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 901 // AVX-NEXT: store half [[MUL_RL]], ptr [[RETVAL_REALP]], align 2 902 // AVX-NEXT: store half [[MUL_IL]], ptr [[RETVAL_IMAGP]], align 2 903 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 904 // AVX-NEXT: ret <2 x half> [[TMP1]] 905 // 906 // X86-LABEL: @mul_half_cr( 907 // X86-NEXT: entry: 908 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 909 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 910 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 911 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 912 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 913 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 914 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 915 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 916 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 917 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 918 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 919 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 920 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 921 // X86-NEXT: [[MUL_RL:%.*]] = fmul float [[EXT]], [[EXT2]] 922 // X86-NEXT: [[MUL_IL:%.*]] = fmul float [[EXT1]], [[EXT2]] 923 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_RL]] to half 924 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[MUL_IL]] to half 925 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 926 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 927 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 928 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 929 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 930 // X86-NEXT: ret <2 x half> [[TMP1]] 931 // 932 _Float16 _Complex mul_half_cr(_Float16 _Complex a, _Float16 b) { 933 return a * b; 934 } 935 936 // AVX-LABEL: @mul_half_rc( 937 // AVX-NEXT: entry: 938 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 939 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 940 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 941 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 942 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 943 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 944 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 945 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 946 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 947 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 948 // AVX-NEXT: [[MUL_RL:%.*]] = fmul half [[TMP0]], [[B_REAL]] 949 // AVX-NEXT: [[MUL_IR:%.*]] = fmul half [[TMP0]], [[B_IMAG]] 950 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 951 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 952 // AVX-NEXT: store half [[MUL_RL]], ptr [[RETVAL_REALP]], align 2 953 // AVX-NEXT: store half [[MUL_IR]], ptr [[RETVAL_IMAGP]], align 2 954 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 955 // AVX-NEXT: ret <2 x half> [[TMP1]] 956 // 957 // X86-LABEL: @mul_half_rc( 958 // X86-NEXT: entry: 959 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 960 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 961 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 962 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 963 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 964 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 965 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 966 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 967 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 968 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 969 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 970 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 971 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 972 // X86-NEXT: [[MUL_RL:%.*]] = fmul float [[EXT]], [[EXT1]] 973 // X86-NEXT: [[MUL_IR:%.*]] = fmul float [[EXT]], [[EXT2]] 974 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[MUL_RL]] to half 975 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[MUL_IR]] to half 976 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 977 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 978 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 979 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 980 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 981 // X86-NEXT: ret <2 x half> [[TMP1]] 982 // 983 _Float16 _Complex mul_half_rc(_Float16 a, _Float16 _Complex b) { 984 return a * b; 985 } 986 987 // AVX-LABEL: @mul_half_cc( 988 // AVX-NEXT: entry: 989 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 990 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 991 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 992 // AVX-NEXT: [[COERCE:%.*]] = alloca { half, half }, align 2 993 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 994 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 995 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 996 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 997 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 998 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 999 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1000 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1001 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1002 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1003 // AVX-NEXT: [[MUL_AC:%.*]] = fmul half [[A_REAL]], [[B_REAL]] 1004 // AVX-NEXT: [[MUL_BD:%.*]] = fmul half [[A_IMAG]], [[B_IMAG]] 1005 // AVX-NEXT: [[MUL_AD:%.*]] = fmul half [[A_REAL]], [[B_IMAG]] 1006 // AVX-NEXT: [[MUL_BC:%.*]] = fmul half [[A_IMAG]], [[B_REAL]] 1007 // AVX-NEXT: [[MUL_R:%.*]] = fsub half [[MUL_AC]], [[MUL_BD]] 1008 // AVX-NEXT: [[MUL_I:%.*]] = fadd half [[MUL_AD]], [[MUL_BC]] 1009 // AVX-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno half [[MUL_R]], [[MUL_R]] 1010 // AVX-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] 1011 // AVX: complex_mul_imag_nan: 1012 // AVX-NEXT: [[ISNAN_CMP1:%.*]] = fcmp uno half [[MUL_I]], [[MUL_I]] 1013 // AVX-NEXT: br i1 [[ISNAN_CMP1]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] 1014 // AVX: complex_mul_libcall: 1015 // AVX-NEXT: [[CALL:%.*]] = call <2 x half> @__mulhc3(half noundef [[A_REAL]], half noundef [[A_IMAG]], half noundef [[B_REAL]], half noundef [[B_IMAG]]) #[[ATTR1:[0-9]+]] 1016 // AVX-NEXT: store <2 x half> [[CALL]], ptr [[COERCE]], align 2 1017 // AVX-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 0 1018 // AVX-NEXT: [[COERCE_REAL:%.*]] = load half, ptr [[COERCE_REALP]], align 2 1019 // AVX-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 1 1020 // AVX-NEXT: [[COERCE_IMAG:%.*]] = load half, ptr [[COERCE_IMAGP]], align 2 1021 // AVX-NEXT: br label [[COMPLEX_MUL_CONT]] 1022 // AVX: complex_mul_cont: 1023 // AVX-NEXT: [[REAL_MUL_PHI:%.*]] = phi half [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] 1024 // AVX-NEXT: [[IMAG_MUL_PHI:%.*]] = phi half [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] 1025 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1026 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1027 // AVX-NEXT: store half [[REAL_MUL_PHI]], ptr [[RETVAL_REALP]], align 2 1028 // AVX-NEXT: store half [[IMAG_MUL_PHI]], ptr [[RETVAL_IMAGP]], align 2 1029 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1030 // AVX-NEXT: ret <2 x half> [[TMP0]] 1031 // 1032 // X86-LABEL: @mul_half_cc( 1033 // X86-NEXT: entry: 1034 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1035 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1036 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 1037 // X86-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 1038 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1039 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 1040 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1041 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1042 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1043 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1044 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1045 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1046 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1047 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1048 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1049 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1050 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 1051 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 1052 // X86-NEXT: [[MUL_AC:%.*]] = fmul float [[EXT]], [[EXT2]] 1053 // X86-NEXT: [[MUL_BD:%.*]] = fmul float [[EXT1]], [[EXT3]] 1054 // X86-NEXT: [[MUL_AD:%.*]] = fmul float [[EXT]], [[EXT3]] 1055 // X86-NEXT: [[MUL_BC:%.*]] = fmul float [[EXT1]], [[EXT2]] 1056 // X86-NEXT: [[MUL_R:%.*]] = fsub float [[MUL_AC]], [[MUL_BD]] 1057 // X86-NEXT: [[MUL_I:%.*]] = fadd float [[MUL_AD]], [[MUL_BC]] 1058 // X86-NEXT: [[ISNAN_CMP:%.*]] = fcmp uno float [[MUL_R]], [[MUL_R]] 1059 // X86-NEXT: br i1 [[ISNAN_CMP]], label [[COMPLEX_MUL_IMAG_NAN:%.*]], label [[COMPLEX_MUL_CONT:%.*]], !prof [[PROF2:![0-9]+]] 1060 // X86: complex_mul_imag_nan: 1061 // X86-NEXT: [[ISNAN_CMP4:%.*]] = fcmp uno float [[MUL_I]], [[MUL_I]] 1062 // X86-NEXT: br i1 [[ISNAN_CMP4]], label [[COMPLEX_MUL_LIBCALL:%.*]], label [[COMPLEX_MUL_CONT]], !prof [[PROF2]] 1063 // X86: complex_mul_libcall: 1064 // X86-NEXT: [[CALL:%.*]] = call <2 x float> @__mulsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT2]], float noundef [[EXT3]]) #[[ATTR2:[0-9]+]] 1065 // X86-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 1066 // X86-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 1067 // X86-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 1068 // X86-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 1069 // X86-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 1070 // X86-NEXT: br label [[COMPLEX_MUL_CONT]] 1071 // X86: complex_mul_cont: 1072 // X86-NEXT: [[REAL_MUL_PHI:%.*]] = phi float [ [[MUL_R]], [[ENTRY:%.*]] ], [ [[MUL_R]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_REAL]], [[COMPLEX_MUL_LIBCALL]] ] 1073 // X86-NEXT: [[IMAG_MUL_PHI:%.*]] = phi float [ [[MUL_I]], [[ENTRY]] ], [ [[MUL_I]], [[COMPLEX_MUL_IMAG_NAN]] ], [ [[COERCE_IMAG]], [[COMPLEX_MUL_LIBCALL]] ] 1074 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[REAL_MUL_PHI]] to half 1075 // X86-NEXT: [[UNPROMOTION5:%.*]] = fptrunc float [[IMAG_MUL_PHI]] to half 1076 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1077 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1078 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1079 // X86-NEXT: store half [[UNPROMOTION5]], ptr [[RETVAL_IMAGP]], align 2 1080 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1081 // X86-NEXT: ret <2 x half> [[TMP0]] 1082 // 1083 _Float16 _Complex mul_half_cc(_Float16 _Complex a, _Float16 _Complex b) { 1084 return a * b; 1085 } 1086 // AVX-LABEL: @div_half_rr( 1087 // AVX-NEXT: entry: 1088 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1089 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1090 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 1091 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1092 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 1093 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1094 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 1095 // AVX-NEXT: [[DIV:%.*]] = fdiv half [[TMP0]], [[TMP1]] 1096 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1097 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1098 // AVX-NEXT: store half [[DIV]], ptr [[RETVAL_REALP]], align 2 1099 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1100 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1101 // AVX-NEXT: ret <2 x half> [[TMP2]] 1102 // 1103 // X86-LABEL: @div_half_rr( 1104 // X86-NEXT: entry: 1105 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1106 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1107 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 1108 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1109 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 1110 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1111 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1112 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[B_ADDR]], align 2 1113 // X86-NEXT: [[EXT1:%.*]] = fpext half [[TMP1]] to float 1114 // X86-NEXT: [[DIV:%.*]] = fdiv float [[EXT]], [[EXT1]] 1115 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[DIV]] to half 1116 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1117 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1118 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1119 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1120 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1121 // X86-NEXT: ret <2 x half> [[TMP2]] 1122 // 1123 _Float16 _Complex div_half_rr(_Float16 a, _Float16 b) { 1124 return a / b; 1125 } 1126 1127 // AVX-LABEL: @div_half_cr( 1128 // AVX-NEXT: entry: 1129 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1130 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1131 // AVX-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 1132 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1133 // AVX-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 1134 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1135 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1136 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1137 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1138 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 1139 // AVX-NEXT: [[TMP1:%.*]] = fdiv half [[A_REAL]], [[TMP0]] 1140 // AVX-NEXT: [[TMP2:%.*]] = fdiv half [[A_IMAG]], [[TMP0]] 1141 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1142 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1143 // AVX-NEXT: store half [[TMP1]], ptr [[RETVAL_REALP]], align 2 1144 // AVX-NEXT: store half [[TMP2]], ptr [[RETVAL_IMAGP]], align 2 1145 // AVX-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1146 // AVX-NEXT: ret <2 x half> [[TMP3]] 1147 // 1148 // X86-LABEL: @div_half_cr( 1149 // X86-NEXT: entry: 1150 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1151 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1152 // X86-NEXT: [[B_ADDR:%.*]] = alloca half, align 2 1153 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1154 // X86-NEXT: store half [[B:%.*]], ptr [[B_ADDR]], align 2 1155 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1156 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1157 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1158 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1159 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1160 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1161 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[B_ADDR]], align 2 1162 // X86-NEXT: [[EXT2:%.*]] = fpext half [[TMP0]] to float 1163 // X86-NEXT: [[TMP1:%.*]] = fdiv float [[EXT]], [[EXT2]] 1164 // X86-NEXT: [[TMP2:%.*]] = fdiv float [[EXT1]], [[EXT2]] 1165 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[TMP1]] to half 1166 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[TMP2]] to half 1167 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1168 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1169 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1170 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 1171 // X86-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1172 // X86-NEXT: ret <2 x half> [[TMP3]] 1173 // 1174 _Float16 _Complex div_half_cr(_Float16 _Complex a, _Float16 b) { 1175 return a / b; 1176 } 1177 // AVX-LABEL: @div_half_rc( 1178 // AVX-NEXT: entry: 1179 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1180 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 1181 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1182 // AVX-NEXT: [[COERCE:%.*]] = alloca { half, half }, align 2 1183 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 1184 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1185 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1186 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1187 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1188 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1189 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1190 // AVX-NEXT: [[CALL:%.*]] = call <2 x half> @__divhc3(half noundef [[TMP0]], half noundef 0xH0000, half noundef [[B_REAL]], half noundef [[B_IMAG]]) #[[ATTR1]] 1191 // AVX-NEXT: store <2 x half> [[CALL]], ptr [[COERCE]], align 2 1192 // AVX-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 0 1193 // AVX-NEXT: [[COERCE_REAL:%.*]] = load half, ptr [[COERCE_REALP]], align 2 1194 // AVX-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 1 1195 // AVX-NEXT: [[COERCE_IMAG:%.*]] = load half, ptr [[COERCE_IMAGP]], align 2 1196 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1197 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1198 // AVX-NEXT: store half [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 2 1199 // AVX-NEXT: store half [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 2 1200 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1201 // AVX-NEXT: ret <2 x half> [[TMP1]] 1202 // 1203 // X86-LABEL: @div_half_rc( 1204 // X86-NEXT: entry: 1205 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1206 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 1207 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1208 // X86-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 1209 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 1210 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1211 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1212 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1213 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1214 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1215 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1216 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1217 // X86-NEXT: [[EXT1:%.*]] = fpext half [[B_REAL]] to float 1218 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_IMAG]] to float 1219 // X86-NEXT: [[CALL:%.*]] = call <2 x float> @__divsc3(float noundef [[EXT]], float noundef 0.000000e+00, float noundef [[EXT1]], float noundef [[EXT2]]) #[[ATTR2]] 1220 // X86-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 1221 // X86-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 1222 // X86-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 1223 // X86-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 1224 // X86-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 1225 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half 1226 // X86-NEXT: [[UNPROMOTION3:%.*]] = fptrunc float [[COERCE_IMAG]] to half 1227 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1228 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1229 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1230 // X86-NEXT: store half [[UNPROMOTION3]], ptr [[RETVAL_IMAGP]], align 2 1231 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1232 // X86-NEXT: ret <2 x half> [[TMP1]] 1233 // 1234 _Float16 _Complex div_half_rc(_Float16 a, _Float16 _Complex b) { 1235 return a / b; 1236 } 1237 1238 // AVX-LABEL: @div_half_cc( 1239 // AVX-NEXT: entry: 1240 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1241 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1242 // AVX-NEXT: [[B:%.*]] = alloca { half, half }, align 2 1243 // AVX-NEXT: [[COERCE:%.*]] = alloca { half, half }, align 2 1244 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1245 // AVX-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 1246 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1247 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1248 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1249 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1250 // AVX-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1251 // AVX-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1252 // AVX-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1253 // AVX-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1254 // AVX-NEXT: [[CALL:%.*]] = call <2 x half> @__divhc3(half noundef [[A_REAL]], half noundef [[A_IMAG]], half noundef [[B_REAL]], half noundef [[B_IMAG]]) #[[ATTR1]] 1255 // AVX-NEXT: store <2 x half> [[CALL]], ptr [[COERCE]], align 2 1256 // AVX-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 0 1257 // AVX-NEXT: [[COERCE_REAL:%.*]] = load half, ptr [[COERCE_REALP]], align 2 1258 // AVX-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[COERCE]], i32 0, i32 1 1259 // AVX-NEXT: [[COERCE_IMAG:%.*]] = load half, ptr [[COERCE_IMAGP]], align 2 1260 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1261 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1262 // AVX-NEXT: store half [[COERCE_REAL]], ptr [[RETVAL_REALP]], align 2 1263 // AVX-NEXT: store half [[COERCE_IMAG]], ptr [[RETVAL_IMAGP]], align 2 1264 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1265 // AVX-NEXT: ret <2 x half> [[TMP0]] 1266 // 1267 // X86-LABEL: @div_half_cc( 1268 // X86-NEXT: entry: 1269 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1270 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1271 // X86-NEXT: [[B:%.*]] = alloca { half, half }, align 2 1272 // X86-NEXT: [[COERCE:%.*]] = alloca { float, float }, align 4 1273 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1274 // X86-NEXT: store <2 x half> [[B_COERCE:%.*]], ptr [[B]], align 2 1275 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1276 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1277 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1278 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1279 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1280 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1281 // X86-NEXT: [[B_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 0 1282 // X86-NEXT: [[B_REAL:%.*]] = load half, ptr [[B_REALP]], align 2 1283 // X86-NEXT: [[B_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[B]], i32 0, i32 1 1284 // X86-NEXT: [[B_IMAG:%.*]] = load half, ptr [[B_IMAGP]], align 2 1285 // X86-NEXT: [[EXT2:%.*]] = fpext half [[B_REAL]] to float 1286 // X86-NEXT: [[EXT3:%.*]] = fpext half [[B_IMAG]] to float 1287 // X86-NEXT: [[CALL:%.*]] = call <2 x float> @__divsc3(float noundef [[EXT]], float noundef [[EXT1]], float noundef [[EXT2]], float noundef [[EXT3]]) #[[ATTR2]] 1288 // X86-NEXT: store <2 x float> [[CALL]], ptr [[COERCE]], align 4 1289 // X86-NEXT: [[COERCE_REALP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 0 1290 // X86-NEXT: [[COERCE_REAL:%.*]] = load float, ptr [[COERCE_REALP]], align 4 1291 // X86-NEXT: [[COERCE_IMAGP:%.*]] = getelementptr inbounds nuw { float, float }, ptr [[COERCE]], i32 0, i32 1 1292 // X86-NEXT: [[COERCE_IMAG:%.*]] = load float, ptr [[COERCE_IMAGP]], align 4 1293 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[COERCE_REAL]] to half 1294 // X86-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[COERCE_IMAG]] to half 1295 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1296 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1297 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1298 // X86-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 1299 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1300 // X86-NEXT: ret <2 x half> [[TMP0]] 1301 // 1302 _Float16 _Complex div_half_cc(_Float16 _Complex a, _Float16 _Complex b) { 1303 return a / b; 1304 } 1305 1306 // AVX-LABEL: @addcompound_half_rr( 1307 // AVX-NEXT: entry: 1308 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1309 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1310 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 1311 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1312 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 1313 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1314 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 1315 // AVX-NEXT: [[ADD:%.*]] = fadd half [[TMP1]], [[TMP0]] 1316 // AVX-NEXT: store half [[ADD]], ptr [[C_ADDR]], align 2 1317 // AVX-NEXT: [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2 1318 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1319 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1320 // AVX-NEXT: store half [[TMP2]], ptr [[RETVAL_REALP]], align 2 1321 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1322 // AVX-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1323 // AVX-NEXT: ret <2 x half> [[TMP3]] 1324 // 1325 // X86-LABEL: @addcompound_half_rr( 1326 // X86-NEXT: entry: 1327 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1328 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1329 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 1330 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1331 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 1332 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1333 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1334 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 1335 // X86-NEXT: [[CONV:%.*]] = fpext half [[TMP1]] to float 1336 // X86-NEXT: [[ADD:%.*]] = fadd float [[CONV]], [[EXT]] 1337 // X86-NEXT: [[CONV1:%.*]] = fptrunc float [[ADD]] to half 1338 // X86-NEXT: store half [[CONV1]], ptr [[C_ADDR]], align 2 1339 // X86-NEXT: [[TMP2:%.*]] = load half, ptr [[C_ADDR]], align 2 1340 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1341 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1342 // X86-NEXT: store half [[TMP2]], ptr [[RETVAL_REALP]], align 2 1343 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1344 // X86-NEXT: [[TMP3:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1345 // X86-NEXT: ret <2 x half> [[TMP3]] 1346 // 1347 _Float16 _Complex addcompound_half_rr(_Float16 a, _Float16 c) { 1348 c += a; 1349 return c; 1350 } 1351 1352 // AVX-LABEL: @addcompound_half_cr( 1353 // AVX-NEXT: entry: 1354 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1355 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1356 // AVX-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 1357 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1358 // AVX-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 1359 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1360 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1361 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1362 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1363 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[C_ADDR]], align 2 1364 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[TMP0]], [[A_REAL]] 1365 // AVX-NEXT: store half [[ADD_R]], ptr [[C_ADDR]], align 2 1366 // AVX-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 1367 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1368 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1369 // AVX-NEXT: store half [[TMP1]], ptr [[RETVAL_REALP]], align 2 1370 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1371 // AVX-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1372 // AVX-NEXT: ret <2 x half> [[TMP2]] 1373 // 1374 // X86-LABEL: @addcompound_half_cr( 1375 // X86-NEXT: entry: 1376 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1377 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1378 // X86-NEXT: [[C_ADDR:%.*]] = alloca half, align 2 1379 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1380 // X86-NEXT: store half [[C:%.*]], ptr [[C_ADDR]], align 2 1381 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1382 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1383 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1384 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1385 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1386 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1387 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[C_ADDR]], align 2 1388 // X86-NEXT: [[CONV:%.*]] = fpext half [[TMP0]] to float 1389 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[CONV]], [[EXT]] 1390 // X86-NEXT: [[CONV2:%.*]] = fptrunc float [[ADD_R]] to half 1391 // X86-NEXT: store half [[CONV2]], ptr [[C_ADDR]], align 2 1392 // X86-NEXT: [[TMP1:%.*]] = load half, ptr [[C_ADDR]], align 2 1393 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1394 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1395 // X86-NEXT: store half [[TMP1]], ptr [[RETVAL_REALP]], align 2 1396 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1397 // X86-NEXT: [[TMP2:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1398 // X86-NEXT: ret <2 x half> [[TMP2]] 1399 // 1400 _Float16 _Complex addcompound_half_cr(_Float16 _Complex a, _Float16 c) { 1401 c += a; 1402 return c; 1403 } 1404 1405 // AVX-LABEL: @addcompound_half_rc( 1406 // AVX-NEXT: entry: 1407 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1408 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1409 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1410 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1411 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1412 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1413 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1414 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1415 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1416 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1417 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[C_REAL]], [[TMP0]] 1418 // AVX-NEXT: [[C_REALP1:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1419 // AVX-NEXT: [[C_IMAGP2:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1420 // AVX-NEXT: store half [[ADD_R]], ptr [[C_REALP1]], align 2 1421 // AVX-NEXT: store half [[C_IMAG]], ptr [[C_IMAGP2]], align 2 1422 // AVX-NEXT: [[C_REALP3:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1423 // AVX-NEXT: [[C_REAL4:%.*]] = load half, ptr [[C_REALP3]], align 2 1424 // AVX-NEXT: [[C_IMAGP5:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1425 // AVX-NEXT: [[C_IMAG6:%.*]] = load half, ptr [[C_IMAGP5]], align 2 1426 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1427 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1428 // AVX-NEXT: store half [[C_REAL4]], ptr [[RETVAL_REALP]], align 2 1429 // AVX-NEXT: store half [[C_IMAG6]], ptr [[RETVAL_IMAGP]], align 2 1430 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1431 // AVX-NEXT: ret <2 x half> [[TMP1]] 1432 // 1433 // X86-LABEL: @addcompound_half_rc( 1434 // X86-NEXT: entry: 1435 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1436 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1437 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1438 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1439 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1440 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1441 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1442 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1443 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1444 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1445 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1446 // X86-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to float 1447 // X86-NEXT: [[CONV1:%.*]] = fpext half [[C_IMAG]] to float 1448 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[CONV]], [[EXT]] 1449 // X86-NEXT: [[CONV2:%.*]] = fptrunc float [[ADD_R]] to half 1450 // X86-NEXT: [[CONV3:%.*]] = fptrunc float [[CONV1]] to half 1451 // X86-NEXT: [[C_REALP4:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1452 // X86-NEXT: [[C_IMAGP5:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1453 // X86-NEXT: store half [[CONV2]], ptr [[C_REALP4]], align 2 1454 // X86-NEXT: store half [[CONV3]], ptr [[C_IMAGP5]], align 2 1455 // X86-NEXT: [[C_REALP6:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1456 // X86-NEXT: [[C_REAL7:%.*]] = load half, ptr [[C_REALP6]], align 2 1457 // X86-NEXT: [[C_IMAGP8:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1458 // X86-NEXT: [[C_IMAG9:%.*]] = load half, ptr [[C_IMAGP8]], align 2 1459 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1460 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1461 // X86-NEXT: store half [[C_REAL7]], ptr [[RETVAL_REALP]], align 2 1462 // X86-NEXT: store half [[C_IMAG9]], ptr [[RETVAL_IMAGP]], align 2 1463 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1464 // X86-NEXT: ret <2 x half> [[TMP1]] 1465 // 1466 _Float16 _Complex addcompound_half_rc(_Float16 a, _Float16 _Complex c) { 1467 c += a; 1468 return c; 1469 } 1470 1471 // AVX-LABEL: @addcompound_half_cc( 1472 // AVX-NEXT: entry: 1473 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1474 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1475 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1476 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1477 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1478 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1479 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1480 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1481 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1482 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1483 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1484 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1485 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1486 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[C_REAL]], [[A_REAL]] 1487 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[C_IMAG]], [[A_IMAG]] 1488 // AVX-NEXT: [[C_REALP1:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1489 // AVX-NEXT: [[C_IMAGP2:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1490 // AVX-NEXT: store half [[ADD_R]], ptr [[C_REALP1]], align 2 1491 // AVX-NEXT: store half [[ADD_I]], ptr [[C_IMAGP2]], align 2 1492 // AVX-NEXT: [[C_REALP3:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1493 // AVX-NEXT: [[C_REAL4:%.*]] = load half, ptr [[C_REALP3]], align 2 1494 // AVX-NEXT: [[C_IMAGP5:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1495 // AVX-NEXT: [[C_IMAG6:%.*]] = load half, ptr [[C_IMAGP5]], align 2 1496 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1497 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1498 // AVX-NEXT: store half [[C_REAL4]], ptr [[RETVAL_REALP]], align 2 1499 // AVX-NEXT: store half [[C_IMAG6]], ptr [[RETVAL_IMAGP]], align 2 1500 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1501 // AVX-NEXT: ret <2 x half> [[TMP0]] 1502 // 1503 // X86-LABEL: @addcompound_half_cc( 1504 // X86-NEXT: entry: 1505 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1506 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1507 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1508 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1509 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1510 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1511 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1512 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1513 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1514 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1515 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1516 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1517 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1518 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1519 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1520 // X86-NEXT: [[CONV:%.*]] = fpext half [[C_REAL]] to float 1521 // X86-NEXT: [[CONV2:%.*]] = fpext half [[C_IMAG]] to float 1522 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[CONV]], [[EXT]] 1523 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[CONV2]], [[EXT1]] 1524 // X86-NEXT: [[CONV3:%.*]] = fptrunc float [[ADD_R]] to half 1525 // X86-NEXT: [[CONV4:%.*]] = fptrunc float [[ADD_I]] to half 1526 // X86-NEXT: [[C_REALP5:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1527 // X86-NEXT: [[C_IMAGP6:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1528 // X86-NEXT: store half [[CONV3]], ptr [[C_REALP5]], align 2 1529 // X86-NEXT: store half [[CONV4]], ptr [[C_IMAGP6]], align 2 1530 // X86-NEXT: [[C_REALP7:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1531 // X86-NEXT: [[C_REAL8:%.*]] = load half, ptr [[C_REALP7]], align 2 1532 // X86-NEXT: [[C_IMAGP9:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1533 // X86-NEXT: [[C_IMAG10:%.*]] = load half, ptr [[C_IMAGP9]], align 2 1534 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1535 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1536 // X86-NEXT: store half [[C_REAL8]], ptr [[RETVAL_REALP]], align 2 1537 // X86-NEXT: store half [[C_IMAG10]], ptr [[RETVAL_IMAGP]], align 2 1538 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1539 // X86-NEXT: ret <2 x half> [[TMP0]] 1540 // 1541 _Float16 _Complex addcompound_half_cc(_Float16 _Complex a, _Float16 _Complex c) { 1542 c += a; 1543 return c; 1544 } 1545 1546 // AVX-LABEL: @MinusOp_r( 1547 // AVX-NEXT: entry: 1548 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1549 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1550 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1551 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1552 // AVX-NEXT: [[FNEG:%.*]] = fneg half [[TMP0]] 1553 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1554 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1555 // AVX-NEXT: store half [[FNEG]], ptr [[RETVAL_REALP]], align 2 1556 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1557 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1558 // AVX-NEXT: ret <2 x half> [[TMP1]] 1559 // 1560 // X86-LABEL: @MinusOp_r( 1561 // X86-NEXT: entry: 1562 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1563 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1564 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1565 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1566 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1567 // X86-NEXT: [[FNEG:%.*]] = fneg float [[EXT]] 1568 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[FNEG]] to half 1569 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1570 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1571 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1572 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1573 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1574 // X86-NEXT: ret <2 x half> [[TMP1]] 1575 // 1576 _Float16 _Complex MinusOp_r(_Float16 a) { 1577 return -a; 1578 } 1579 1580 // AVX-LABEL: @MinusOp_c( 1581 // AVX-NEXT: entry: 1582 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1583 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1584 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1585 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1586 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1587 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1588 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1589 // AVX-NEXT: [[NEG_R:%.*]] = fneg half [[A_REAL]] 1590 // AVX-NEXT: [[NEG_I:%.*]] = fneg half [[A_IMAG]] 1591 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1592 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1593 // AVX-NEXT: store half [[NEG_R]], ptr [[RETVAL_REALP]], align 2 1594 // AVX-NEXT: store half [[NEG_I]], ptr [[RETVAL_IMAGP]], align 2 1595 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1596 // AVX-NEXT: ret <2 x half> [[TMP0]] 1597 // 1598 // X86-LABEL: @MinusOp_c( 1599 // X86-NEXT: entry: 1600 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1601 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1602 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1603 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1604 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1605 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1606 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1607 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1608 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1609 // X86-NEXT: [[NEG_R:%.*]] = fneg float [[EXT]] 1610 // X86-NEXT: [[NEG_I:%.*]] = fneg float [[EXT1]] 1611 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[NEG_R]] to half 1612 // X86-NEXT: [[UNPROMOTION2:%.*]] = fptrunc float [[NEG_I]] to half 1613 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1614 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1615 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1616 // X86-NEXT: store half [[UNPROMOTION2]], ptr [[RETVAL_IMAGP]], align 2 1617 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1618 // X86-NEXT: ret <2 x half> [[TMP0]] 1619 // 1620 _Float16 _Complex MinusOp_c(_Float16 _Complex a) { 1621 return -a; 1622 } 1623 1624 // AVX-LABEL: @PlusOp_r( 1625 // AVX-NEXT: entry: 1626 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1627 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1628 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1629 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1630 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1631 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1632 // AVX-NEXT: store half [[TMP0]], ptr [[RETVAL_REALP]], align 2 1633 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1634 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1635 // AVX-NEXT: ret <2 x half> [[TMP1]] 1636 // 1637 // X86-LABEL: @PlusOp_r( 1638 // X86-NEXT: entry: 1639 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1640 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1641 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1642 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1643 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1644 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half 1645 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1646 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1647 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1648 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1649 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1650 // X86-NEXT: ret <2 x half> [[TMP1]] 1651 // 1652 _Float16 _Complex PlusOp_r(_Float16 a) { 1653 return +a; 1654 } 1655 1656 // AVX-LABEL: @PlusOp_c( 1657 // AVX-NEXT: entry: 1658 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1659 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1660 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1661 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1662 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1663 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1664 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1665 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1666 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1667 // AVX-NEXT: store half [[A_REAL]], ptr [[RETVAL_REALP]], align 2 1668 // AVX-NEXT: store half [[A_IMAG]], ptr [[RETVAL_IMAGP]], align 2 1669 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1670 // AVX-NEXT: ret <2 x half> [[TMP0]] 1671 // 1672 // X86-LABEL: @PlusOp_c( 1673 // X86-NEXT: entry: 1674 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1675 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1676 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1677 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1678 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1679 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1680 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1681 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1682 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1683 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half 1684 // X86-NEXT: [[UNPROMOTION2:%.*]] = fptrunc float [[EXT1]] to half 1685 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1686 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1687 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1688 // X86-NEXT: store half [[UNPROMOTION2]], ptr [[RETVAL_IMAGP]], align 2 1689 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1690 // X86-NEXT: ret <2 x half> [[TMP0]] 1691 // 1692 _Float16 _Complex PlusOp_c(_Float16 _Complex a) { 1693 return +a; 1694 } 1695 1696 // AVX-LABEL: @RealOp_r( 1697 // AVX-NEXT: entry: 1698 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1699 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1700 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1701 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1702 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1703 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1704 // AVX-NEXT: store half [[TMP0]], ptr [[RETVAL_REALP]], align 2 1705 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1706 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1707 // AVX-NEXT: ret <2 x half> [[TMP1]] 1708 // 1709 // X86-LABEL: @RealOp_r( 1710 // X86-NEXT: entry: 1711 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1712 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1713 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1714 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1715 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1716 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half 1717 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1718 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1719 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1720 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1721 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1722 // X86-NEXT: ret <2 x half> [[TMP1]] 1723 // 1724 _Float16 _Complex RealOp_r(_Float16 a) { 1725 return +a; 1726 } 1727 1728 // AVX-LABEL: @RealOp_c( 1729 // AVX-NEXT: entry: 1730 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1731 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1732 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1733 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1734 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_REALP]], align 2 1735 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1736 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1737 // AVX-NEXT: store half [[TMP0]], ptr [[RETVAL_REALP]], align 2 1738 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1739 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1740 // AVX-NEXT: ret <2 x half> [[TMP1]] 1741 // 1742 // X86-LABEL: @RealOp_c( 1743 // X86-NEXT: entry: 1744 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1745 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1746 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1747 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1748 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1749 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1750 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half 1751 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1752 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1753 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1754 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1755 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1756 // X86-NEXT: ret <2 x half> [[TMP0]] 1757 // 1758 _Float16 _Complex RealOp_c(_Float16 _Complex a) { 1759 return __real a; 1760 } 1761 1762 // AVX-LABEL: @ImagOp_r( 1763 // AVX-NEXT: entry: 1764 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1765 // AVX-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1766 // AVX-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1767 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1768 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1769 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1770 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_REALP]], align 2 1771 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1772 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1773 // AVX-NEXT: ret <2 x half> [[TMP1]] 1774 // 1775 // X86-LABEL: @ImagOp_r( 1776 // X86-NEXT: entry: 1777 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1778 // X86-NEXT: [[A_ADDR:%.*]] = alloca half, align 2 1779 // X86-NEXT: store half [[A:%.*]], ptr [[A_ADDR]], align 2 1780 // X86-NEXT: [[TMP0:%.*]] = load half, ptr [[A_ADDR]], align 2 1781 // X86-NEXT: [[EXT:%.*]] = fpext half [[TMP0]] to float 1782 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1783 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1784 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_REALP]], align 2 1785 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1786 // X86-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1787 // X86-NEXT: ret <2 x half> [[TMP1]] 1788 // 1789 _Float16 _Complex ImagOp_r(_Float16 a) { 1790 return __imag a; 1791 } 1792 1793 // AVX-LABEL: @ImagOp_c( 1794 // AVX-NEXT: entry: 1795 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1796 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1797 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1798 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1799 // AVX-NEXT: [[TMP0:%.*]] = load half, ptr [[A_IMAGP]], align 2 1800 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1801 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1802 // AVX-NEXT: store half [[TMP0]], ptr [[RETVAL_REALP]], align 2 1803 // AVX-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1804 // AVX-NEXT: [[TMP1:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1805 // AVX-NEXT: ret <2 x half> [[TMP1]] 1806 // 1807 // X86-LABEL: @ImagOp_c( 1808 // X86-NEXT: entry: 1809 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1810 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1811 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1812 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1813 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1814 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_IMAG]] to float 1815 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[EXT]] to half 1816 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1817 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1818 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1819 // X86-NEXT: store half 0xH0000, ptr [[RETVAL_IMAGP]], align 2 1820 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1821 // X86-NEXT: ret <2 x half> [[TMP0]] 1822 // 1823 _Float16 _Complex ImagOp_c(_Float16 _Complex a) { 1824 return __imag a; 1825 } 1826 1827 // AVX-LABEL: @MinusOp_c_c( 1828 // AVX-NEXT: entry: 1829 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1830 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1831 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1832 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1833 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1834 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1835 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1836 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1837 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1838 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1839 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1840 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1841 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1842 // AVX-NEXT: [[NEG_R:%.*]] = fneg half [[C_REAL]] 1843 // AVX-NEXT: [[NEG_I:%.*]] = fneg half [[C_IMAG]] 1844 // AVX-NEXT: [[ADD_R:%.*]] = fadd half [[A_REAL]], [[NEG_R]] 1845 // AVX-NEXT: [[ADD_I:%.*]] = fadd half [[A_IMAG]], [[NEG_I]] 1846 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1847 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1848 // AVX-NEXT: store half [[ADD_R]], ptr [[RETVAL_REALP]], align 2 1849 // AVX-NEXT: store half [[ADD_I]], ptr [[RETVAL_IMAGP]], align 2 1850 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1851 // AVX-NEXT: ret <2 x half> [[TMP0]] 1852 // 1853 // X86-LABEL: @MinusOp_c_c( 1854 // X86-NEXT: entry: 1855 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1856 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1857 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1858 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1859 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1860 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1861 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1862 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1863 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1864 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1865 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1866 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1867 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1868 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1869 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1870 // X86-NEXT: [[EXT2:%.*]] = fpext half [[C_REAL]] to float 1871 // X86-NEXT: [[EXT3:%.*]] = fpext half [[C_IMAG]] to float 1872 // X86-NEXT: [[NEG_R:%.*]] = fneg float [[EXT2]] 1873 // X86-NEXT: [[NEG_I:%.*]] = fneg float [[EXT3]] 1874 // X86-NEXT: [[ADD_R:%.*]] = fadd float [[EXT]], [[NEG_R]] 1875 // X86-NEXT: [[ADD_I:%.*]] = fadd float [[EXT1]], [[NEG_I]] 1876 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[ADD_R]] to half 1877 // X86-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[ADD_I]] to half 1878 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1879 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1880 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1881 // X86-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 1882 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1883 // X86-NEXT: ret <2 x half> [[TMP0]] 1884 // 1885 _Float16 _Complex MinusOp_c_c(_Float16 _Complex a, _Float16 _Complex c) { 1886 return a + -c; 1887 } 1888 1889 // AVX-LABEL: @PlusOp_c_c( 1890 // AVX-NEXT: entry: 1891 // AVX-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1892 // AVX-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1893 // AVX-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1894 // AVX-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1895 // AVX-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1896 // AVX-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1897 // AVX-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1898 // AVX-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1899 // AVX-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1900 // AVX-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1901 // AVX-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1902 // AVX-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1903 // AVX-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1904 // AVX-NEXT: [[SUB_R:%.*]] = fsub half [[A_REAL]], [[C_REAL]] 1905 // AVX-NEXT: [[SUB_I:%.*]] = fsub half [[A_IMAG]], [[C_IMAG]] 1906 // AVX-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1907 // AVX-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1908 // AVX-NEXT: store half [[SUB_R]], ptr [[RETVAL_REALP]], align 2 1909 // AVX-NEXT: store half [[SUB_I]], ptr [[RETVAL_IMAGP]], align 2 1910 // AVX-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1911 // AVX-NEXT: ret <2 x half> [[TMP0]] 1912 // 1913 // X86-LABEL: @PlusOp_c_c( 1914 // X86-NEXT: entry: 1915 // X86-NEXT: [[RETVAL:%.*]] = alloca { half, half }, align 2 1916 // X86-NEXT: [[A:%.*]] = alloca { half, half }, align 2 1917 // X86-NEXT: [[C:%.*]] = alloca { half, half }, align 2 1918 // X86-NEXT: store <2 x half> [[A_COERCE:%.*]], ptr [[A]], align 2 1919 // X86-NEXT: store <2 x half> [[C_COERCE:%.*]], ptr [[C]], align 2 1920 // X86-NEXT: [[A_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 0 1921 // X86-NEXT: [[A_REAL:%.*]] = load half, ptr [[A_REALP]], align 2 1922 // X86-NEXT: [[A_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[A]], i32 0, i32 1 1923 // X86-NEXT: [[A_IMAG:%.*]] = load half, ptr [[A_IMAGP]], align 2 1924 // X86-NEXT: [[EXT:%.*]] = fpext half [[A_REAL]] to float 1925 // X86-NEXT: [[EXT1:%.*]] = fpext half [[A_IMAG]] to float 1926 // X86-NEXT: [[C_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 0 1927 // X86-NEXT: [[C_REAL:%.*]] = load half, ptr [[C_REALP]], align 2 1928 // X86-NEXT: [[C_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[C]], i32 0, i32 1 1929 // X86-NEXT: [[C_IMAG:%.*]] = load half, ptr [[C_IMAGP]], align 2 1930 // X86-NEXT: [[EXT2:%.*]] = fpext half [[C_REAL]] to float 1931 // X86-NEXT: [[EXT3:%.*]] = fpext half [[C_IMAG]] to float 1932 // X86-NEXT: [[SUB_R:%.*]] = fsub float [[EXT]], [[EXT2]] 1933 // X86-NEXT: [[SUB_I:%.*]] = fsub float [[EXT1]], [[EXT3]] 1934 // X86-NEXT: [[UNPROMOTION:%.*]] = fptrunc float [[SUB_R]] to half 1935 // X86-NEXT: [[UNPROMOTION4:%.*]] = fptrunc float [[SUB_I]] to half 1936 // X86-NEXT: [[RETVAL_REALP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 0 1937 // X86-NEXT: [[RETVAL_IMAGP:%.*]] = getelementptr inbounds nuw { half, half }, ptr [[RETVAL]], i32 0, i32 1 1938 // X86-NEXT: store half [[UNPROMOTION]], ptr [[RETVAL_REALP]], align 2 1939 // X86-NEXT: store half [[UNPROMOTION4]], ptr [[RETVAL_IMAGP]], align 2 1940 // X86-NEXT: [[TMP0:%.*]] = load <2 x half>, ptr [[RETVAL]], align 2 1941 // X86-NEXT: ret <2 x half> [[TMP0]] 1942 // 1943 _Float16 _Complex PlusOp_c_c(_Float16 _Complex a, _Float16 _Complex c) { 1944 return a - +c; 1945 } 1946