1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=instcombine -S < %s | FileCheck %s 3 4declare half @llvm.amdgcn.sqrt.f16(half) 5declare float @llvm.amdgcn.sqrt.f32(float) 6declare double @llvm.amdgcn.sqrt.f64(double) 7 8declare half @llvm.amdgcn.rcp.f16(half) 9declare float @llvm.amdgcn.rcp.f32(float) 10declare double @llvm.amdgcn.rcp.f64(double) 11 12declare half @llvm.amdgcn.rsq.f16(half) 13declare float @llvm.amdgcn.rsq.f32(float) 14declare double @llvm.amdgcn.rsq.f64(double) 15 16 17declare half @llvm.sqrt.f16(half) 18declare float @llvm.sqrt.f32(float) 19declare double @llvm.sqrt.f64(double) 20 21; Should allow precision increasing contraction to rsq call 22define float @amdgcn_rcp_amdgcn_sqrt_f32_contract(float %x) { 23; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract 24; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1:[0-9]+]] { 25; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]]) 26; CHECK-NEXT: ret float [[RSQ]] 27; 28 %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x) 29 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 30 ret float %rsq 31} 32 33; contract required on both calls 34define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0(float %x) { 35; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0 36; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 37; CHECK-NEXT: [[SQRT:%.*]] = call float @llvm.amdgcn.sqrt.f32(float [[X]]) 38; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]]) 39; CHECK-NEXT: ret float [[RSQ]] 40; 41 %sqrt = call float @llvm.amdgcn.sqrt.f32(float %x) 42 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 43 ret float %rsq 44} 45 46; contract required on both calls 47define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1(float %x) { 48; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1 49; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 50; CHECK-NEXT: [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]]) 51; CHECK-NEXT: [[RSQ:%.*]] = call float @llvm.amdgcn.rcp.f32(float [[SQRT]]) 52; CHECK-NEXT: ret float [[RSQ]] 53; 54 %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x) 55 %rsq = call float @llvm.amdgcn.rcp.f32(float %sqrt) 56 ret float %rsq 57} 58 59; Reject from multiple uses of sqrt 60define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use(float %x, ptr %ptr) { 61; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract_multi_use 62; CHECK-SAME: (float [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] { 63; CHECK-NEXT: [[SQRT:%.*]] = call contract float @llvm.amdgcn.sqrt.f32(float [[X]]) 64; CHECK-NEXT: store float [[SQRT]], ptr [[PTR]], align 4 65; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]]) 66; CHECK-NEXT: ret float [[RSQ]] 67; 68 %sqrt = call contract float @llvm.amdgcn.sqrt.f32(float %x) 69 store float %sqrt, ptr %ptr 70 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 71 ret float %rsq 72} 73 74; Test flags are or'd together 75define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract(float %x) { 76; CHECK-LABEL: define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract 77; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 78; CHECK-NEXT: [[RSQ:%.*]] = call nnan ninf contract float @llvm.amdgcn.rsq.f32(float [[X]]) 79; CHECK-NEXT: ret float [[RSQ]] 80; 81 %sqrt = call nnan contract float @llvm.amdgcn.sqrt.f32(float %x) 82 %rsq = call ninf contract float @llvm.amdgcn.rcp.f32(float %sqrt) 83 ret float %rsq 84} 85 86; Should allow precision increasing contraction to rsq call 87define half @amdgcn_rcp_amdgcn_sqrt_f16_contract(half %x) { 88; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract 89; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] { 90; CHECK-NEXT: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]]) 91; CHECK-NEXT: ret half [[RSQ]] 92; 93 %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x) 94 %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt) 95 ret half %rsq 96} 97 98; contract required on both calls 99define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0(half %x) { 100; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0 101; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] { 102; CHECK-NEXT: [[SQRT:%.*]] = call half @llvm.sqrt.f16(half [[X]]) 103; CHECK-NEXT: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]]) 104; CHECK-NEXT: ret half [[RSQ]] 105; 106 %sqrt = call half @llvm.amdgcn.sqrt.f16(half %x) 107 %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt) 108 ret half %rsq 109} 110 111; contract required on both calls 112define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1(half %x) { 113; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1 114; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] { 115; CHECK-NEXT: [[SQRT:%.*]] = call contract half @llvm.sqrt.f16(half [[X]]) 116; CHECK-NEXT: [[RSQ:%.*]] = call half @llvm.amdgcn.rcp.f16(half [[SQRT]]) 117; CHECK-NEXT: ret half [[RSQ]] 118; 119 %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x) 120 %rsq = call half @llvm.amdgcn.rcp.f16(half %sqrt) 121 ret half %rsq 122} 123 124; Reject from multiple uses of sqrt 125define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use(half %x, ptr %ptr) { 126; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract_multi_use 127; CHECK-SAME: (half [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] { 128; CHECK-NEXT: [[SQRT:%.*]] = call contract half @llvm.sqrt.f16(half [[X]]) 129; CHECK-NEXT: store half [[SQRT]], ptr [[PTR]], align 2 130; CHECK-NEXT: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rcp.f16(half [[SQRT]]) 131; CHECK-NEXT: ret half [[RSQ]] 132; 133 %sqrt = call contract half @llvm.amdgcn.sqrt.f16(half %x) 134 store half %sqrt, ptr %ptr 135 %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt) 136 ret half %rsq 137} 138 139; Test flags are or'd together 140define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract(half %x) { 141; CHECK-LABEL: define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract 142; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] { 143; CHECK-NEXT: [[RSQ:%.*]] = call nnan ninf contract half @llvm.amdgcn.rsq.f16(half [[X]]) 144; CHECK-NEXT: ret half [[RSQ]] 145; 146 %sqrt = call nnan contract half @llvm.amdgcn.sqrt.f16(half %x) 147 %rsq = call ninf contract half @llvm.amdgcn.rcp.f16(half %sqrt) 148 ret half %rsq 149} 150 151; Should allow precision increasing contraction to rsq call 152define double @amdgcn_rcp_amdgcn_sqrt_f64_contract(double %x) { 153; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract 154; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 155; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rsq.f64(double [[X]]) 156; CHECK-NEXT: ret double [[RSQ]] 157; 158 %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x) 159 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 160 ret double %rsq 161} 162 163; contract required on both calls 164define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0(double %x) { 165; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0 166; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 167; CHECK-NEXT: [[SQRT:%.*]] = call double @llvm.amdgcn.sqrt.f64(double [[X]]) 168; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 169; CHECK-NEXT: ret double [[RSQ]] 170; 171 %sqrt = call double @llvm.amdgcn.sqrt.f64(double %x) 172 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 173 ret double %rsq 174} 175 176; contract required on both calls 177define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1(double %x) { 178; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1 179; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 180; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]]) 181; CHECK-NEXT: [[RSQ:%.*]] = call double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 182; CHECK-NEXT: ret double [[RSQ]] 183; 184 %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x) 185 %rsq = call double @llvm.amdgcn.rcp.f64(double %sqrt) 186 ret double %rsq 187} 188 189; Reject from multiple uses of sqrt 190define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use(double %x, ptr %ptr) { 191; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract_multi_use 192; CHECK-SAME: (double [[X:%.*]], ptr [[PTR:%.*]]) #[[ATTR1]] { 193; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.amdgcn.sqrt.f64(double [[X]]) 194; CHECK-NEXT: store double [[SQRT]], ptr [[PTR]], align 8 195; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 196; CHECK-NEXT: ret double [[RSQ]] 197; 198 %sqrt = call contract double @llvm.amdgcn.sqrt.f64(double %x) 199 store double %sqrt, ptr %ptr 200 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 201 ret double %rsq 202} 203 204; Test flags are or'd together 205define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract(double %x) { 206; CHECK-LABEL: define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract 207; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 208; CHECK-NEXT: [[RSQ:%.*]] = call nnan ninf contract double @llvm.amdgcn.rsq.f64(double [[X]]) 209; CHECK-NEXT: ret double [[RSQ]] 210; 211 %sqrt = call nnan contract double @llvm.amdgcn.sqrt.f64(double %x) 212 %rsq = call ninf contract double @llvm.amdgcn.rcp.f64(double %sqrt) 213 ret double %rsq 214} 215 216; Do not contract with regular sqrt 217define float @amdgcn_rcp_sqrt_f32_contract(float %x) { 218; CHECK-LABEL: define float @amdgcn_rcp_sqrt_f32_contract 219; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 220; CHECK-NEXT: [[SQRT:%.*]] = call contract float @llvm.sqrt.f32(float [[X]]) 221; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rcp.f32(float [[SQRT]]) 222; CHECK-NEXT: ret float [[RSQ]] 223; 224 %sqrt = call contract float @llvm.sqrt.f32(float %x) 225 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 226 ret float %rsq 227} 228 229; Do contract with regular sqrt for f16 230define half @amdgcn_rcp_sqrt_f16_contract(half %x) { 231; CHECK-LABEL: define half @amdgcn_rcp_sqrt_f16_contract 232; CHECK-SAME: (half [[X:%.*]]) #[[ATTR1]] { 233; CHECK-NEXT: [[RSQ:%.*]] = call contract half @llvm.amdgcn.rsq.f16(half [[X]]) 234; CHECK-NEXT: ret half [[RSQ]] 235; 236 %sqrt = call contract half @llvm.sqrt.f16(half %x) 237 %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt) 238 ret half %rsq 239} 240 241; Do not contract with regular sqrt 242define double @amdgcn_rcp_sqrt_f64_contract(double %x) { 243; CHECK-LABEL: define double @amdgcn_rcp_sqrt_f64_contract 244; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 245; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]) 246; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 247; CHECK-NEXT: ret double [[RSQ]] 248; 249 %sqrt = call contract double @llvm.sqrt.f64(double %x) 250 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 251 ret double %rsq 252} 253 254define float @amdgcn_rcp_afn_sqrt_f32_contract(float %x) { 255; CHECK-LABEL: define float @amdgcn_rcp_afn_sqrt_f32_contract 256; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 257; CHECK-NEXT: [[RSQ:%.*]] = call contract afn float @llvm.amdgcn.rsq.f32(float [[X]]) 258; CHECK-NEXT: ret float [[RSQ]] 259; 260 %sqrt = call afn contract float @llvm.sqrt.f32(float %x) 261 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 262 ret float %rsq 263} 264 265define float @amdgcn_rcp_fpmath3_sqrt_f32_contract(float %x) { 266; CHECK-LABEL: define float @amdgcn_rcp_fpmath3_sqrt_f32_contract 267; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 268; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]]) 269; CHECK-NEXT: ret float [[RSQ]] 270; 271 %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !0 272 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 273 ret float %rsq 274} 275 276define float @amdgcn_rcp_fpmath1_sqrt_f32_contract(float %x) { 277; CHECK-LABEL: define float @amdgcn_rcp_fpmath1_sqrt_f32_contract 278; CHECK-SAME: (float [[X:%.*]]) #[[ATTR1]] { 279; CHECK-NEXT: [[RSQ:%.*]] = call contract float @llvm.amdgcn.rsq.f32(float [[X]]) 280; CHECK-NEXT: ret float [[RSQ]] 281; 282 %sqrt = call contract float @llvm.sqrt.f32(float %x), !fpmath !1 283 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt) 284 ret float %rsq 285} 286 287; Ignore f64 sqrt 288define double @amdgcn_rcp_afn_sqrt_f64_contract(double %x) { 289; CHECK-LABEL: define double @amdgcn_rcp_afn_sqrt_f64_contract 290; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 291; CHECK-NEXT: [[SQRT:%.*]] = call contract afn double @llvm.sqrt.f64(double [[X]]) 292; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 293; CHECK-NEXT: ret double [[RSQ]] 294; 295 %sqrt = call afn contract double @llvm.sqrt.f64(double %x) 296 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 297 ret double %rsq 298} 299 300; Ignore f64 sqrt 301define double @amdgcn_rcp_fpmath3_sqrt_f64_contract(double %x) { 302; CHECK-LABEL: define double @amdgcn_rcp_fpmath3_sqrt_f64_contract 303; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 304; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !0 305; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 306; CHECK-NEXT: ret double [[RSQ]] 307; 308 %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !0 309 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 310 ret double %rsq 311} 312 313; Ignore f64 sqrt 314define double @amdgcn_rcp_fpmath1_sqrt_f64_contract(double %x) { 315; CHECK-LABEL: define double @amdgcn_rcp_fpmath1_sqrt_f64_contract 316; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] { 317; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath !1 318; CHECK-NEXT: [[RSQ:%.*]] = call contract double @llvm.amdgcn.rcp.f64(double [[SQRT]]) 319; CHECK-NEXT: ret double [[RSQ]] 320; 321 %sqrt = call contract double @llvm.sqrt.f64(double %x), !fpmath !1 322 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt) 323 ret double %rsq 324} 325 326!0 = !{float 3.0} 327!1 = !{float 1.0} 328