328 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 22; RUN: opt -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -passes=instcombine -S < %s | FileCheck %s3 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 call22define float @amdgcn_rcp_amdgcn_sqrt_f32_contract(float %x) {23; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_contract24; 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 %rsq31}32 33; contract required on both calls34define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract0(float %x) {35; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract036; 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 %rsq44}45 46; contract required on both calls47define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract1(float %x) {48; CHECK-LABEL: define float @amdgcn_rcp_amdgcn_sqrt_f32_missing_contract149; 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 %rsq57}58 59; Reject from multiple uses of sqrt60define 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_use62; 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 465; 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 %ptr70 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)71 ret float %rsq72}73 74; Test flags are or'd together75define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract(float %x) {76; CHECK-LABEL: define float @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f32_contract77; 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 %rsq84}85 86; Should allow precision increasing contraction to rsq call87define half @amdgcn_rcp_amdgcn_sqrt_f16_contract(half %x) {88; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_contract89; 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 %rsq96}97 98; contract required on both calls99define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0(half %x) {100; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract0101; 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 %rsq109}110 111; contract required on both calls112define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1(half %x) {113; CHECK-LABEL: define half @amdgcn_rcp_amdgcn_sqrt_f16_missing_contract1114; 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 %rsq122}123 124; Reject from multiple uses of sqrt125define 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_use127; 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 2130; 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 %ptr135 %rsq = call contract half @llvm.amdgcn.rcp.f16(half %sqrt)136 ret half %rsq137}138 139; Test flags are or'd together140define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract(half %x) {141; CHECK-LABEL: define half @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f16_contract142; 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 %rsq149}150 151; Should allow precision increasing contraction to rsq call152define double @amdgcn_rcp_amdgcn_sqrt_f64_contract(double %x) {153; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_contract154; 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 %rsq161}162 163; contract required on both calls164define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0(double %x) {165; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract0166; 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 %rsq174}175 176; contract required on both calls177define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1(double %x) {178; CHECK-LABEL: define double @amdgcn_rcp_amdgcn_sqrt_f64_missing_contract1179; 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 %rsq187}188 189; Reject from multiple uses of sqrt190define 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_use192; 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 8195; 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 %ptr200 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)201 ret double %rsq202}203 204; Test flags are or'd together205define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract(double %x) {206; CHECK-LABEL: define double @amdgcn_rcp_nnan_amdgcn_sqrt_ninf_f64_contract207; 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 %rsq214}215 216; Do not contract with regular sqrt217define float @amdgcn_rcp_sqrt_f32_contract(float %x) {218; CHECK-LABEL: define float @amdgcn_rcp_sqrt_f32_contract219; 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 %rsq227}228 229; Do contract with regular sqrt for f16230define half @amdgcn_rcp_sqrt_f16_contract(half %x) {231; CHECK-LABEL: define half @amdgcn_rcp_sqrt_f16_contract232; 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 %rsq239}240 241; Do not contract with regular sqrt242define double @amdgcn_rcp_sqrt_f64_contract(double %x) {243; CHECK-LABEL: define double @amdgcn_rcp_sqrt_f64_contract244; 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 %rsq252}253 254define float @amdgcn_rcp_afn_sqrt_f32_contract(float %x) {255; CHECK-LABEL: define float @amdgcn_rcp_afn_sqrt_f32_contract256; 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 %rsq263}264 265define float @amdgcn_rcp_fpmath3_sqrt_f32_contract(float %x) {266; CHECK-LABEL: define float @amdgcn_rcp_fpmath3_sqrt_f32_contract267; 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 !0272 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)273 ret float %rsq274}275 276define float @amdgcn_rcp_fpmath1_sqrt_f32_contract(float %x) {277; CHECK-LABEL: define float @amdgcn_rcp_fpmath1_sqrt_f32_contract278; 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 !1283 %rsq = call contract float @llvm.amdgcn.rcp.f32(float %sqrt)284 ret float %rsq285}286 287; Ignore f64 sqrt288define double @amdgcn_rcp_afn_sqrt_f64_contract(double %x) {289; CHECK-LABEL: define double @amdgcn_rcp_afn_sqrt_f64_contract290; 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 %rsq298}299 300; Ignore f64 sqrt301define double @amdgcn_rcp_fpmath3_sqrt_f64_contract(double %x) {302; CHECK-LABEL: define double @amdgcn_rcp_fpmath3_sqrt_f64_contract303; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {304; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath [[META0:![0-9]+]]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 !0309 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)310 ret double %rsq311}312 313; Ignore f64 sqrt314define double @amdgcn_rcp_fpmath1_sqrt_f64_contract(double %x) {315; CHECK-LABEL: define double @amdgcn_rcp_fpmath1_sqrt_f64_contract316; CHECK-SAME: (double [[X:%.*]]) #[[ATTR1]] {317; CHECK-NEXT: [[SQRT:%.*]] = call contract double @llvm.sqrt.f64(double [[X]]), !fpmath [[META1:![0-9]+]]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 !1322 %rsq = call contract double @llvm.amdgcn.rcp.f64(double %sqrt)323 ret double %rsq324}325 326!0 = !{float 3.0}327!1 = !{float 1.0}328