1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -mtriple=amdgcn-amd-amdhsa -instcombine -S | FileCheck %s 3 4define float @ldexp_f32_undef_undef() { 5; CHECK-LABEL: @ldexp_f32_undef_undef( 6; CHECK-NEXT: ret float 0x7FF8000000000000 7; 8 %call = call float @llvm.amdgcn.ldexp.f32(float undef, i32 undef) 9 ret float %call 10} 11 12; If the exponent is 0, it doesn't matter if the first argument is 13; constant or not. 14define void @ldexp_f32_exp0(float %x) { 15; CHECK-LABEL: @ldexp_f32_exp0( 16; CHECK-NEXT: store volatile float [[X:%.*]], float addrspace(1)* undef, align 4 17; CHECK-NEXT: store volatile float [[X]], float addrspace(1)* undef, align 4 18; CHECK-NEXT: [[ONE:%.*]] = call float @llvm.amdgcn.ldexp.f32(float [[X]], i32 1) 19; CHECK-NEXT: store volatile float [[ONE]], float addrspace(1)* undef, align 4 20; CHECK-NEXT: ret void 21; 22 %zero = call float @llvm.amdgcn.ldexp.f32(float %x, i32 0) 23 store volatile float %zero, float addrspace(1)* undef 24 25 %undef = call float @llvm.amdgcn.ldexp.f32(float %x, i32 undef) 26 store volatile float %undef, float addrspace(1)* undef 27 28 %one = call float @llvm.amdgcn.ldexp.f32(float %x, i32 1) 29 store volatile float %one, float addrspace(1)* undef 30 ret void 31} 32 33; Test variable exponent but zero or undef value. 34define void @ldexp_f32_val0(i32 %y) { 35; CHECK-LABEL: @ldexp_f32_val0( 36; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 37; CHECK-NEXT: store volatile float -0.000000e+00, float addrspace(1)* undef, align 4 38; CHECK-NEXT: store volatile float 0x7FF8000000000000, float addrspace(1)* undef, align 4 39; CHECK-NEXT: ret void 40; 41 %zero = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 %y) 42 store volatile float %zero, float addrspace(1)* undef 43 44 %neg.zero = call float @llvm.amdgcn.ldexp.f32(float -0.0, i32 %y) 45 store volatile float %neg.zero, float addrspace(1)* undef 46 47 %undef = call float @llvm.amdgcn.ldexp.f32(float undef, i32 %y) 48 store volatile float %undef, float addrspace(1)* undef 49 ret void 50} 51 52define void @ldexp_f32_val_infinity(i32 %y) { 53; CHECK-LABEL: @ldexp_f32_val_infinity( 54; CHECK-NEXT: store volatile float 0x7FF0000000000000, float addrspace(1)* undef, align 4 55; CHECK-NEXT: store volatile float 0xFFF0000000000000, float addrspace(1)* undef, align 4 56; CHECK-NEXT: store volatile float 0x7FF0000000000000, float addrspace(1)* undef, align 4 57; CHECK-NEXT: store volatile float 0xFFF0000000000000, float addrspace(1)* undef, align 4 58; CHECK-NEXT: ret void 59; 60 %inf = call float @llvm.amdgcn.ldexp.f32(float 0x7ff0000000000000, i32 %y) 61 store volatile float %inf, float addrspace(1)* undef 62 63 %neg.inf = call float @llvm.amdgcn.ldexp.f32(float 0xfff0000000000000, i32 %y) 64 store volatile float %neg.inf, float addrspace(1)* undef 65 66 %inf.zero = call float @llvm.amdgcn.ldexp.f32(float 0x7ff0000000000000, i32 0) 67 store volatile float %inf.zero, float addrspace(1)* undef 68 69 %neg.inf.zero = call float @llvm.amdgcn.ldexp.f32(float 0xfff0000000000000, i32 0) 70 store volatile float %neg.inf.zero, float addrspace(1)* undef 71 72 ret void 73} 74 75; Signaling nan should be quieted. 76; Technically this depends on the ieee_mode in the mode register. 77define void @ldexp_f32_val_nan(i32 %y) { 78; CHECK-LABEL: @ldexp_f32_val_nan( 79; CHECK-NEXT: store volatile float 0x7FF8001000000000, float addrspace(1)* undef, align 4 80; CHECK-NEXT: store volatile float 0xFFF8000100000000, float addrspace(1)* undef, align 4 81; CHECK-NEXT: store volatile float 0x7FF8000020000000, float addrspace(1)* undef, align 4 82; CHECK-NEXT: store volatile float 0xFFFFFFFFE0000000, float addrspace(1)* undef, align 4 83; CHECK-NEXT: ret void 84; 85 %plus.qnan = call float @llvm.amdgcn.ldexp.f32(float 0x7ff0001000000000, i32 %y) 86 store volatile float %plus.qnan, float addrspace(1)* undef 87 88 %neg.qnan = call float @llvm.amdgcn.ldexp.f32(float 0xfff0000100000000, i32 %y) 89 store volatile float %neg.qnan, float addrspace(1)* undef 90 91 %plus.snan = call float @llvm.amdgcn.ldexp.f32(float 0x7FF0000020000000, i32 %y) 92 store volatile float %plus.snan, float addrspace(1)* undef 93 94 %neg.snan = call float @llvm.amdgcn.ldexp.f32(float 0xFFF7FFFFE0000000, i32 %y) 95 store volatile float %neg.snan, float addrspace(1)* undef 96 97 ret void 98} 99 100define void @ldexp_f32_val_nan_strictfp(i32 %y) #0 { 101; CHECK-LABEL: @ldexp_f32_val_nan_strictfp( 102; CHECK-NEXT: [[PLUS_QNAN:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0x7FF0001000000000, i32 [[Y:%.*]]) [[ATTR0:#.*]] 103; CHECK-NEXT: store volatile float [[PLUS_QNAN]], float addrspace(1)* undef, align 4 104; CHECK-NEXT: [[NEG_QNAN:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0xFFF0000100000000, i32 [[Y]]) [[ATTR0]] 105; CHECK-NEXT: store volatile float [[NEG_QNAN]], float addrspace(1)* undef, align 4 106; CHECK-NEXT: [[PLUS_SNAN:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0x7FF0000020000000, i32 [[Y]]) [[ATTR0]] 107; CHECK-NEXT: store volatile float [[PLUS_SNAN]], float addrspace(1)* undef, align 4 108; CHECK-NEXT: [[NEG_SNAN:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0xFFF7FFFFE0000000, i32 [[Y]]) [[ATTR0]] 109; CHECK-NEXT: store volatile float [[NEG_SNAN]], float addrspace(1)* undef, align 4 110; CHECK-NEXT: store volatile float 0x7FF8000000000000, float addrspace(1)* undef, align 4 111; CHECK-NEXT: ret void 112; 113 %plus.qnan = call float @llvm.amdgcn.ldexp.f32(float 0x7ff0001000000000, i32 %y) #0 114 store volatile float %plus.qnan, float addrspace(1)* undef 115 116 %neg.qnan = call float @llvm.amdgcn.ldexp.f32(float 0xfff0000100000000, i32 %y) #0 117 store volatile float %neg.qnan, float addrspace(1)* undef 118 119 %plus.snan = call float @llvm.amdgcn.ldexp.f32(float 0x7FF0000020000000, i32 %y) #0 120 store volatile float %plus.snan, float addrspace(1)* undef 121 122 %neg.snan = call float @llvm.amdgcn.ldexp.f32(float 0xFFF7FFFFE0000000, i32 %y) #0 123 store volatile float %neg.snan, float addrspace(1)* undef 124 125 %undef = call float @llvm.amdgcn.ldexp.f32(float undef, i32 %y) #0 126 store volatile float %undef, float addrspace(1)* undef 127 128 ret void 129} 130 131define void @ldexp_f32_0() { 132; CHECK-LABEL: @ldexp_f32_0( 133; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 134; CHECK-NEXT: store volatile float -0.000000e+00, float addrspace(1)* undef, align 4 135; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 136; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 137; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 138; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 139; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 140; CHECK-NEXT: ret void 141; 142 %zero = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 0) 143 store volatile float %zero, float addrspace(1)* undef 144 145 %neg.zero = call float @llvm.amdgcn.ldexp.f32(float -0.0, i32 0) 146 store volatile float %neg.zero, float addrspace(1)* undef 147 148 %one = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 1) 149 store volatile float %one, float addrspace(1)* undef 150 151 %min.exp = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 -126) 152 store volatile float %min.exp, float addrspace(1)* undef 153 154 %min.exp.sub1 = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 -127) 155 store volatile float %min.exp.sub1, float addrspace(1)* undef 156 157 %max.exp = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 127) 158 store volatile float %max.exp, float addrspace(1)* undef 159 160 %max.exp.plus1 = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 128) 161 store volatile float %max.exp.plus1, float addrspace(1)* undef 162 163 ret void 164} 165 166; Should be able to ignore strictfp in this case 167define void @ldexp_f32_0_strictfp(float %x) #0 { 168; CHECK-LABEL: @ldexp_f32_0_strictfp( 169; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 170; CHECK-NEXT: store volatile float -0.000000e+00, float addrspace(1)* undef, align 4 171; CHECK-NEXT: store volatile float 0.000000e+00, float addrspace(1)* undef, align 4 172; CHECK-NEXT: [[UNKNOWN_ZERO:%.*]] = call float @llvm.amdgcn.ldexp.f32(float [[X:%.*]], i32 0) [[ATTR0]] 173; CHECK-NEXT: store volatile float [[UNKNOWN_ZERO]], float addrspace(1)* undef, align 4 174; CHECK-NEXT: [[UNKNOWN_UNDEF:%.*]] = call float @llvm.amdgcn.ldexp.f32(float [[X]], i32 undef) [[ATTR0]] 175; CHECK-NEXT: store volatile float [[UNKNOWN_UNDEF]], float addrspace(1)* undef, align 4 176; CHECK-NEXT: [[DENORMAL_0:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 0) [[ATTR0]] 177; CHECK-NEXT: store volatile float [[DENORMAL_0]], float addrspace(1)* undef, align 4 178; CHECK-NEXT: [[DENORMAL_1:%.*]] = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 1) [[ATTR0]] 179; CHECK-NEXT: store volatile float [[DENORMAL_1]], float addrspace(1)* undef, align 4 180; CHECK-NEXT: ret void 181; 182 %zero = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 0) #0 183 store volatile float %zero, float addrspace(1)* undef 184 185 %neg.zero = call float @llvm.amdgcn.ldexp.f32(float -0.0, i32 0) #0 186 store volatile float %neg.zero, float addrspace(1)* undef 187 188 %one = call float @llvm.amdgcn.ldexp.f32(float 0.0, i32 1) #0 189 store volatile float %one, float addrspace(1)* undef 190 191 %unknown.zero = call float @llvm.amdgcn.ldexp.f32(float %x, i32 0) #0 192 store volatile float %unknown.zero, float addrspace(1)* undef 193 194 %unknown.undef = call float @llvm.amdgcn.ldexp.f32(float %x, i32 undef) #0 195 store volatile float %unknown.undef, float addrspace(1)* undef 196 197 %denormal.0 = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 0) #0 198 store volatile float %denormal.0, float addrspace(1)* undef 199 200 %denormal.1 = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 1) #0 201 store volatile float %denormal.1, float addrspace(1)* undef 202 203 ret void 204} 205 206define void @ldexp_f32() { 207; CHECK-LABEL: @ldexp_f32( 208; CHECK-NEXT: store volatile float 2.000000e+00, float addrspace(1)* undef, align 4 209; CHECK-NEXT: store volatile float 4.000000e+00, float addrspace(1)* undef, align 4 210; CHECK-NEXT: store volatile float 8.000000e+00, float addrspace(1)* undef, align 4 211; CHECK-NEXT: store volatile float 5.000000e-01, float addrspace(1)* undef, align 4 212; CHECK-NEXT: store volatile float 0x3810000000000000, float addrspace(1)* undef, align 4 213; CHECK-NEXT: store volatile float 0x3800000000000000, float addrspace(1)* undef, align 4 214; CHECK-NEXT: store volatile float 0x47E0000000000000, float addrspace(1)* undef, align 4 215; CHECK-NEXT: store volatile float 0x7FF0000000000000, float addrspace(1)* undef, align 4 216; CHECK-NEXT: store volatile float -2.000000e+00, float addrspace(1)* undef, align 4 217; CHECK-NEXT: store volatile float -4.000000e+00, float addrspace(1)* undef, align 4 218; CHECK-NEXT: store volatile float -8.000000e+00, float addrspace(1)* undef, align 4 219; CHECK-NEXT: store volatile float -5.000000e-01, float addrspace(1)* undef, align 4 220; CHECK-NEXT: store volatile float 0xB810000000000000, float addrspace(1)* undef, align 4 221; CHECK-NEXT: store volatile float 0xB800000000000000, float addrspace(1)* undef, align 4 222; CHECK-NEXT: store volatile float 0xC7E0000000000000, float addrspace(1)* undef, align 4 223; CHECK-NEXT: store volatile float 0xFFF0000000000000, float addrspace(1)* undef, align 4 224; CHECK-NEXT: store volatile float 0x44D5000000000000, float addrspace(1)* undef, align 4 225; CHECK-NEXT: ret void 226; 227 %one.one = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 1) 228 store volatile float %one.one, float addrspace(1)* undef 229 230 %one.two = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 2) 231 store volatile float %one.two, float addrspace(1)* undef 232 233 %one.three = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 3) 234 store volatile float %one.three, float addrspace(1)* undef 235 236 %one.negone = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 -1) 237 store volatile float %one.negone, float addrspace(1)* undef 238 239 %one.min.exp = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 -126) 240 store volatile float %one.min.exp, float addrspace(1)* undef 241 242 %one.min.exp.sub1 = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 -127) 243 store volatile float %one.min.exp.sub1, float addrspace(1)* undef 244 245 %one.max.exp = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 127) 246 store volatile float %one.max.exp, float addrspace(1)* undef 247 248 %one.max.exp.plus1 = call float @llvm.amdgcn.ldexp.f32(float 1.0, i32 128) 249 store volatile float %one.max.exp.plus1, float addrspace(1)* undef 250 251 %neg.one.one = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 1) 252 store volatile float %neg.one.one, float addrspace(1)* undef 253 254 %neg.one.two = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 2) 255 store volatile float %neg.one.two, float addrspace(1)* undef 256 257 %neg.one.three = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 3) 258 store volatile float %neg.one.three, float addrspace(1)* undef 259 260 %neg.one.negone = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 -1) 261 store volatile float %neg.one.negone, float addrspace(1)* undef 262 263 %neg.one.min.exp = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 -126) 264 store volatile float %neg.one.min.exp, float addrspace(1)* undef 265 266 %neg.one.min.exp.sub1 = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 -127) 267 store volatile float %neg.one.min.exp.sub1, float addrspace(1)* undef 268 269 %neg.one.max.exp = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 127) 270 store volatile float %neg.one.max.exp, float addrspace(1)* undef 271 272 %neg.one.max.exp.plus1 = call float @llvm.amdgcn.ldexp.f32(float -1.0, i32 128) 273 store volatile float %neg.one.max.exp.plus1, float addrspace(1)* undef 274 275 %fortytwo.seven = call float @llvm.amdgcn.ldexp.f32(float 42.0, i32 73) 276 store volatile float %fortytwo.seven, float addrspace(1)* undef 277 278 ret void 279} 280 281; Technically we should probably flush these depending on the expected 282; denormal mode of the function, but no other IR constant folding 283; considers this. 284define void @ldexp_f32_denormal() { 285; CHECK-LABEL: @ldexp_f32_denormal( 286; CHECK-NEXT: store volatile float 0x380FFFFFC0000000, float addrspace(1)* undef, align 4 287; CHECK-NEXT: store volatile float 0x381FFFFFC0000000, float addrspace(1)* undef, align 4 288; CHECK-NEXT: ret void 289; 290 %denormal.0 = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 0) 291 store volatile float %denormal.0, float addrspace(1)* undef 292 293 %denormal.1 = call float @llvm.amdgcn.ldexp.f32(float 0x380FFFFFC0000000, i32 1) 294 store volatile float %denormal.1, float addrspace(1)* undef 295 296 ret void 297} 298 299define void @ldexp_f64() { 300; CHECK-LABEL: @ldexp_f64( 301; CHECK-NEXT: store volatile double 2.000000e+00, double addrspace(1)* undef, align 8 302; CHECK-NEXT: store volatile double 4.000000e+00, double addrspace(1)* undef, align 8 303; CHECK-NEXT: store volatile double 0x44D5000000000000, double addrspace(1)* undef, align 8 304; CHECK-NEXT: ret void 305; 306 %one.one = call double @llvm.amdgcn.ldexp.f64(double 1.0, i32 1) 307 store volatile double %one.one, double addrspace(1)* undef 308 309 %one.two = call double @llvm.amdgcn.ldexp.f64(double 1.0, i32 2) 310 store volatile double %one.two, double addrspace(1)* undef 311 312 %fortytwo.seven = call double @llvm.amdgcn.ldexp.f64(double 42.0, i32 73) 313 store volatile double %fortytwo.seven, double addrspace(1)* undef 314 315 ret void 316} 317 318define void @ldexp_f16() { 319; CHECK-LABEL: @ldexp_f16( 320; CHECK-NEXT: store volatile half 0xH4000, half addrspace(1)* undef, align 2 321; CHECK-NEXT: store volatile half 0xH4400, half addrspace(1)* undef, align 2 322; CHECK-NEXT: store volatile half 0xH7C00, half addrspace(1)* undef, align 2 323; CHECK-NEXT: ret void 324; 325 %one.one = call half @llvm.amdgcn.ldexp.f16(half 1.0, i32 1) 326 store volatile half %one.one, half addrspace(1)* undef 327 328 %one.two = call half @llvm.amdgcn.ldexp.f16(half 1.0, i32 2) 329 store volatile half %one.two, half addrspace(1)* undef 330 331 %fortytwo.seven = call half @llvm.amdgcn.ldexp.f16(half 42.0, i32 73) 332 store volatile half %fortytwo.seven, half addrspace(1)* undef 333 334 ret void 335} 336 337declare half @llvm.amdgcn.ldexp.f16(half, i32) #1 338declare float @llvm.amdgcn.ldexp.f32(float, i32) #1 339declare double @llvm.amdgcn.ldexp.f64(double, i32) #1 340 341attributes #0 = { strictfp } 342attributes #1 = { nounwind readnone speculatable } 343