865 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S -o - %s | FileCheck %s3 4; Check that we don't replace `atomicrmw <op> LHS, 0` with `load atomic LHS`.5; Doing that would lose the store semantic of the `atomicrmw` operation.6; This may enable some other optimizations that would otherwise be illegal when7; the store semantic was present (e.g., like dropping a fence).8 9; Idempotent atomicrmw are still canonicalized.10define i32 @atomic_add_zero(ptr %addr) {11; CHECK-LABEL: @atomic_add_zero(12; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 413; CHECK-NEXT: ret i32 [[RES]]14;15 %res = atomicrmw add ptr %addr, i32 0 monotonic16 ret i32 %res17}18 19define i32 @atomic_or_zero(ptr %addr) {20; CHECK-LABEL: @atomic_or_zero(21; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 422; CHECK-NEXT: ret i32 [[RES]]23;24 %res = atomicrmw or ptr %addr, i32 0 monotonic25 ret i32 %res26}27 28; Idempotent atomicrmw are still canonicalized.29define i32 @atomic_sub_zero(ptr %addr) {30; CHECK-LABEL: @atomic_sub_zero(31; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 432; CHECK-NEXT: ret i32 [[RES]]33;34 %res = atomicrmw sub ptr %addr, i32 0 monotonic35 ret i32 %res36}37 38; Idempotent atomicrmw are still canonicalized.39define i32 @atomic_and_allones(ptr %addr) {40; CHECK-LABEL: @atomic_and_allones(41; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 442; CHECK-NEXT: ret i32 [[RES]]43;44 %res = atomicrmw and ptr %addr, i32 -1 monotonic45 ret i32 %res46}47 48; Idempotent atomicrmw are still canonicalized.49define i32 @atomic_umin_uint_max(ptr %addr) {50; CHECK-LABEL: @atomic_umin_uint_max(51; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 452; CHECK-NEXT: ret i32 [[RES]]53;54 %res = atomicrmw umin ptr %addr, i32 -1 monotonic55 ret i32 %res56}57 58; Idempotent atomicrmw are still canonicalized.59define i32 @atomic_umax_zero(ptr %addr) {60; CHECK-LABEL: @atomic_umax_zero(61; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 monotonic, align 462; CHECK-NEXT: ret i32 [[RES]]63;64 %res = atomicrmw umax ptr %addr, i32 0 monotonic65 ret i32 %res66}67 68; Idempotent atomicrmw are still canonicalized.69define i8 @atomic_min_smax_char(ptr %addr) {70; CHECK-LABEL: @atomic_min_smax_char(71; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i8 0 monotonic, align 172; CHECK-NEXT: ret i8 [[RES]]73;74 %res = atomicrmw min ptr %addr, i8 127 monotonic75 ret i8 %res76}77 78; Idempotent atomicrmw are still canonicalized.79define i8 @atomic_max_smin_char(ptr %addr) {80; CHECK-LABEL: @atomic_max_smin_char(81; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i8 0 monotonic, align 182; CHECK-NEXT: ret i8 [[RES]]83;84 %res = atomicrmw max ptr %addr, i8 -128 monotonic85 ret i8 %res86}87 88; Idempotent atomicrmw are still canonicalized.89define float @atomic_fsub_zero(ptr %addr) {90; CHECK-LABEL: @atomic_fsub_zero(91; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 monotonic, align 492; CHECK-NEXT: ret float [[RES]]93;94 %res = atomicrmw fsub ptr %addr, float 0.0 monotonic95 ret float %res96}97 98define float @atomic_fadd_zero(ptr %addr) {99; CHECK-LABEL: @atomic_fadd_zero(100; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 monotonic, align 4101; CHECK-NEXT: ret float [[RES]]102;103 %res = atomicrmw fadd ptr %addr, float -0.0 monotonic104 ret float %res105}106 107; Idempotent atomicrmw are still canonicalized.108define float @atomic_fsub_canon(ptr %addr) {109; CHECK-LABEL: @atomic_fsub_canon(110; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 release, align 4111; CHECK-NEXT: ret float [[RES]]112;113 %res = atomicrmw fsub ptr %addr, float 0.0 release114 ret float %res115}116 117define float @atomic_fadd_canon(ptr %addr) {118; CHECK-LABEL: @atomic_fadd_canon(119; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 release, align 4120; CHECK-NEXT: ret float [[RES]]121;122 %res = atomicrmw fadd ptr %addr, float -0.0 release123 ret float %res124}125 126; Can't replace a volatile w/a load; this would eliminate a volatile store.127define i64 @atomic_sub_zero_volatile(ptr %addr) {128; CHECK-LABEL: @atomic_sub_zero_volatile(129; CHECK-NEXT: [[RES:%.*]] = atomicrmw volatile sub ptr [[ADDR:%.*]], i64 0 acquire, align 8130; CHECK-NEXT: ret i64 [[RES]]131;132 %res = atomicrmw volatile sub ptr %addr, i64 0 acquire133 ret i64 %res134}135 136 137; Check that the transformation properly preserve the syncscope.138; Idempotent atomicrmw are still canonicalized.139define i16 @atomic_syncscope(ptr %addr) {140; CHECK-LABEL: @atomic_syncscope(141; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 syncscope("some_syncscope") acquire, align 2142; CHECK-NEXT: ret i16 [[RES]]143;144 %res = atomicrmw or ptr %addr, i16 0 syncscope("some_syncscope") acquire145 ret i16 %res146}147 148; By eliminating the store part of the atomicrmw, we would get rid of the149; release semantic, which is incorrect. We can canonicalize the operation.150define i16 @atomic_seq_cst(ptr %addr) {151; CHECK-LABEL: @atomic_seq_cst(152; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 seq_cst, align 2153; CHECK-NEXT: ret i16 [[RES]]154;155 %res = atomicrmw add ptr %addr, i16 0 seq_cst156 ret i16 %res157}158 159; Check that the transformation does not apply when the value is changed by160; the atomic operation (non zero constant).161define i16 @atomic_add_non_zero(ptr %addr) {162; CHECK-LABEL: @atomic_add_non_zero(163; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr [[ADDR:%.*]], i16 2 monotonic, align 2164; CHECK-NEXT: ret i16 [[RES]]165;166 %res = atomicrmw add ptr %addr, i16 2 monotonic167 ret i16 %res168}169 170; Idempotent atomicrmw are still canonicalized.171define i16 @atomic_xor_zero(ptr %addr) {172; CHECK-LABEL: @atomic_xor_zero(173; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 monotonic, align 2174; CHECK-NEXT: ret i16 [[RES]]175;176 %res = atomicrmw xor ptr %addr, i16 0 monotonic177 ret i16 %res178}179 180; Check that the transformation does not apply when the ordering is181; incompatible with a load (release). Do canonicalize.182define i16 @atomic_release(ptr %addr) {183; CHECK-LABEL: @atomic_release(184; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 release, align 2185; CHECK-NEXT: ret i16 [[RES]]186;187 %res = atomicrmw sub ptr %addr, i16 0 release188 ret i16 %res189}190 191; Check that the transformation does not apply when the ordering is192; incompatible with a load (acquire, release). Do canonicalize.193define i16 @atomic_acq_rel(ptr %addr) {194; CHECK-LABEL: @atomic_acq_rel(195; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 acq_rel, align 2196; CHECK-NEXT: ret i16 [[RES]]197;198 %res = atomicrmw xor ptr %addr, i16 0 acq_rel199 ret i16 %res200}201 202define i32 @sat_or_allones(ptr %addr) {203; CHECK-LABEL: @sat_or_allones(204; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 monotonic, align 4205; CHECK-NEXT: ret i32 [[RES]]206;207 %res = atomicrmw or ptr %addr, i32 -1 monotonic208 ret i32 %res209}210 211define i32 @sat_and_zero(ptr %addr) {212; CHECK-LABEL: @sat_and_zero(213; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 monotonic, align 4214; CHECK-NEXT: ret i32 [[RES]]215;216 %res = atomicrmw and ptr %addr, i32 0 monotonic217 ret i32 %res218}219 220define i32 @sat_umin_uint_min(ptr %addr) {221; CHECK-LABEL: @sat_umin_uint_min(222; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 monotonic, align 4223; CHECK-NEXT: ret i32 [[RES]]224;225 %res = atomicrmw umin ptr %addr, i32 0 monotonic226 ret i32 %res227}228 229define i32 @sat_umax_uint_max(ptr %addr) {230; CHECK-LABEL: @sat_umax_uint_max(231; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 monotonic, align 4232; CHECK-NEXT: ret i32 [[RES]]233;234 %res = atomicrmw umax ptr %addr, i32 -1 monotonic235 ret i32 %res236}237 238define i8 @sat_min_smin_char(ptr %addr) {239; CHECK-LABEL: @sat_min_smin_char(240; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i8 -128 monotonic, align 1241; CHECK-NEXT: ret i8 [[RES]]242;243 %res = atomicrmw min ptr %addr, i8 -128 monotonic244 ret i8 %res245}246 247define i8 @sat_max_smax_char(ptr %addr) {248; CHECK-LABEL: @sat_max_smax_char(249; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i8 127 monotonic, align 1250; CHECK-NEXT: ret i8 [[RES]]251;252 %res = atomicrmw max ptr %addr, i8 127 monotonic253 ret i8 %res254}255 256define double @sat_fadd_nan(ptr %addr) {257; CHECK-LABEL: @sat_fadd_nan(258; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF release, align 8259; CHECK-NEXT: ret double [[RES]]260;261 %res = atomicrmw fadd ptr %addr, double 0x7FF00000FFFFFFFF release262 ret double %res263}264 265define double @sat_fsub_nan(ptr %addr) {266; CHECK-LABEL: @sat_fsub_nan(267; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF release, align 8268; CHECK-NEXT: ret double [[RES]]269;270 %res = atomicrmw fsub ptr %addr, double 0x7FF00000FFFFFFFF release271 ret double %res272}273 274define void @sat_fsub_nan_unused(ptr %addr) {275; CHECK-LABEL: @sat_fsub_nan_unused(276; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF monotonic, align 8277; CHECK-NEXT: ret void278;279 atomicrmw fsub ptr %addr, double 0x7FF00000FFFFFFFF monotonic280 ret void281}282 283define void @xchg_unused_monotonic(ptr %addr) {284; CHECK-LABEL: @xchg_unused_monotonic(285; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 monotonic, align 4286; CHECK-NEXT: ret void287;288 atomicrmw xchg ptr %addr, i32 0 monotonic289 ret void290}291 292define void @xchg_unused_release(ptr %addr) {293; CHECK-LABEL: @xchg_unused_release(294; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 release, align 4295; CHECK-NEXT: ret void296;297 atomicrmw xchg ptr %addr, i32 -1 release298 ret void299}300 301define void @xchg_unused_under_aligned(ptr %addr) {302; CHECK-LABEL: @xchg_unused_under_aligned(303; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 release, align 1304; CHECK-NEXT: ret void305;306 atomicrmw xchg ptr %addr, i32 -1 release, align 1307 ret void308}309 310define void @xchg_unused_over_aligned(ptr %addr) {311; CHECK-LABEL: @xchg_unused_over_aligned(312; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 release, align 8313; CHECK-NEXT: ret void314;315 atomicrmw xchg ptr %addr, i32 -1 release, align 8316 ret void317}318 319define void @xchg_unused_seq_cst(ptr %addr) {320; CHECK-LABEL: @xchg_unused_seq_cst(321; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 seq_cst, align 4322; CHECK-NEXT: ret void323;324 atomicrmw xchg ptr %addr, i32 0 seq_cst325 ret void326}327 328define void @xchg_unused_volatile(ptr %addr) {329; CHECK-LABEL: @xchg_unused_volatile(330; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw volatile xchg ptr [[ADDR:%.*]], i32 0 monotonic, align 4331; CHECK-NEXT: ret void332;333 atomicrmw volatile xchg ptr %addr, i32 0 monotonic334 ret void335}336 337define void @sat_or_allones_unused(ptr %addr) {338; CHECK-LABEL: @sat_or_allones_unused(339; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 monotonic, align 4340; CHECK-NEXT: ret void341;342 atomicrmw or ptr %addr, i32 -1 monotonic343 ret void344}345 346define void @undef_operand_unused(ptr %addr) {347; CHECK-LABEL: @undef_operand_unused(348; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 undef monotonic, align 4349; CHECK-NEXT: ret void350;351 atomicrmw or ptr %addr, i32 undef monotonic352 ret void353}354 355define i32 @undef_operand_used(ptr %addr) {356; CHECK-LABEL: @undef_operand_used(357; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 undef monotonic, align 4358; CHECK-NEXT: ret i32 [[RES]]359;360 %res = atomicrmw or ptr %addr, i32 undef monotonic361 ret i32 %res362}363 364define double @sat_fmax_inf(ptr %addr) {365; CHECK-LABEL: @sat_fmax_inf(366; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF0000000000000 monotonic, align 8367; CHECK-NEXT: ret double [[RES]]368;369 %res = atomicrmw fmax ptr %addr, double 0x7FF0000000000000 monotonic370 ret double %res371}372 373define double @no_sat_fmax_inf(ptr %addr) {374; CHECK-LABEL: @no_sat_fmax_inf(375; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmax ptr [[ADDR:%.*]], double 1.000000e-01 monotonic, align 8376; CHECK-NEXT: ret double [[RES]]377;378 %res = atomicrmw fmax ptr %addr, double 1.000000e-01 monotonic379 ret double %res380}381 382define double @sat_fmin_inf(ptr %addr) {383; CHECK-LABEL: @sat_fmin_inf(384; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0xFFF0000000000000 monotonic, align 8385; CHECK-NEXT: ret double [[RES]]386;387 %res = atomicrmw fmin ptr %addr, double 0xFFF0000000000000 monotonic388 ret double %res389}390 391define double @no_sat_fmin_inf(ptr %addr) {392; CHECK-LABEL: @no_sat_fmin_inf(393; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmin ptr [[ADDR:%.*]], double 1.000000e-01 monotonic, align 8394; CHECK-NEXT: ret double [[RES]]395;396 %res = atomicrmw fmin ptr %addr, double 1.000000e-01 monotonic397 ret double %res398}399 400define double @sat_fmaximum_inf(ptr %addr) {401; CHECK-LABEL: @sat_fmaximum_inf(402; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmaximum ptr [[ADDR:%.*]], double 0x7FF0000000000000 monotonic, align 8403; CHECK-NEXT: ret double [[RES]]404;405 %res = atomicrmw fmaximum ptr %addr, double 0x7FF0000000000000 monotonic406 ret double %res407}408 409define double @no_sat_fmaximum_inf(ptr %addr) {410; CHECK-LABEL: @no_sat_fmaximum_inf(411; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmaximum ptr [[ADDR:%.*]], double 1.000000e-01 monotonic, align 8412; CHECK-NEXT: ret double [[RES]]413;414 %res = atomicrmw fmaximum ptr %addr, double 1.000000e-01 monotonic415 ret double %res416}417 418define double @sat_fminimum_inf(ptr %addr) {419; CHECK-LABEL: @sat_fminimum_inf(420; CHECK-NEXT: [[RES:%.*]] = atomicrmw fminimum ptr [[ADDR:%.*]], double 0xFFF0000000000000 monotonic, align 8421; CHECK-NEXT: ret double [[RES]]422;423 %res = atomicrmw fminimum ptr %addr, double 0xFFF0000000000000 monotonic424 ret double %res425}426 427define double @no_sat_fminimum_inf(ptr %addr) {428; CHECK-LABEL: @no_sat_fminimum_inf(429; CHECK-NEXT: [[RES:%.*]] = atomicrmw fminimum ptr [[ADDR:%.*]], double 1.000000e-01 monotonic, align 8430; CHECK-NEXT: ret double [[RES]]431;432 %res = atomicrmw fminimum ptr %addr, double 1.000000e-01 monotonic433 ret double %res434}435 436; Idempotent atomicrmw are still canonicalized.437define i32 @atomic_add_zero_preserve_md(ptr %addr) {438; CHECK-LABEL: @atomic_add_zero_preserve_md(439; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0:![0-9]+]], !amdgpu.no.fine.grained.host.memory [[META1:![0-9]+]], !amdgpu.no.remote.memory.access [[META1]]440; CHECK-NEXT: ret i32 [[RES]]441;442 %res = atomicrmw add ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1443 ret i32 %res444}445 446define i32 @atomic_or_zero_preserve_md(ptr %addr) {447; CHECK-LABEL: @atomic_or_zero_preserve_md(448; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]449; CHECK-NEXT: ret i32 [[RES]]450;451 %res = atomicrmw or ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1452 ret i32 %res453}454 455; Idempotent atomicrmw are still canonicalized.456define i32 @atomic_sub_zero_preserve_md(ptr %addr) {457; CHECK-LABEL: @atomic_sub_zero_preserve_md(458; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]459; CHECK-NEXT: ret i32 [[RES]]460;461 %res = atomicrmw sub ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1462 ret i32 %res463}464 465; Idempotent atomicrmw are still canonicalized.466define i32 @atomic_and_allones_preserve_md(ptr %addr) {467; CHECK-LABEL: @atomic_and_allones_preserve_md(468; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]469; CHECK-NEXT: ret i32 [[RES]]470;471 %res = atomicrmw and ptr %addr, i32 -1 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1472 ret i32 %res473}474 475; Idempotent atomicrmw are still canonicalized.476define i32 @atomic_umin_uint_max_preserve_md(ptr %addr) {477; CHECK-LABEL: @atomic_umin_uint_max_preserve_md(478; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]479; CHECK-NEXT: ret i32 [[RES]]480;481 %res = atomicrmw umin ptr %addr, i32 -1 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1482 ret i32 %res483}484 485; Idempotent atomicrmw are still canonicalized.486define i32 @atomic_umax_zero_preserve_md(ptr %addr) {487; CHECK-LABEL: @atomic_umax_zero_preserve_md(488; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]489; CHECK-NEXT: ret i32 [[RES]]490;491 %res = atomicrmw umax ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1492 ret i32 %res493}494 495; Idempotent atomicrmw are still canonicalized.496define i8 @atomic_min_smax_char_preserve_md(ptr %addr) {497; CHECK-LABEL: @atomic_min_smax_char_preserve_md(498; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i8 0 syncscope("agent") monotonic, align 1, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]499; CHECK-NEXT: ret i8 [[RES]]500;501 %res = atomicrmw min ptr %addr, i8 127 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1502 ret i8 %res503}504 505; Idempotent atomicrmw are still canonicalized.506define i8 @atomic_max_smin_char_preserve_md(ptr %addr) {507; CHECK-LABEL: @atomic_max_smin_char_preserve_md(508; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i8 0 syncscope("agent") monotonic, align 1, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]509; CHECK-NEXT: ret i8 [[RES]]510;511 %res = atomicrmw max ptr %addr, i8 -128 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1512 ret i8 %res513}514 515; Idempotent atomicrmw are still canonicalized.516define float @atomic_fsub_zero_preserve_md(ptr %addr) {517; CHECK-LABEL: @atomic_fsub_zero_preserve_md(518; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]519; CHECK-NEXT: ret float [[RES]]520;521 %res = atomicrmw fsub ptr %addr, float 0.0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1522 ret float %res523}524 525define float @atomic_fadd_zero_preserve_md(ptr %addr) {526; CHECK-LABEL: @atomic_fadd_zero_preserve_md(527; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]528; CHECK-NEXT: ret float [[RES]]529;530 %res = atomicrmw fadd ptr %addr, float -0.0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1531 ret float %res532}533 534; Idempotent atomicrmw are still canonicalized.535define float @atomic_fsub_canon_preserve_md(ptr %addr) {536; CHECK-LABEL: @atomic_fsub_canon_preserve_md(537; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 release, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]538; CHECK-NEXT: ret float [[RES]]539;540 %res = atomicrmw fsub ptr %addr, float 0.0 release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1541 ret float %res542}543 544define float @atomic_fadd_canon_preserve_md(ptr %addr) {545; CHECK-LABEL: @atomic_fadd_canon_preserve_md(546; CHECK-NEXT: [[RES:%.*]] = atomicrmw fadd ptr [[ADDR:%.*]], float -0.000000e+00 release, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]547; CHECK-NEXT: ret float [[RES]]548;549 %res = atomicrmw fadd ptr %addr, float -0.0 release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1550 ret float %res551}552 553; Can't replace a volatile w/a load; this would eliminate a volatile store.554define i64 @atomic_sub_zero_volatile_preserve_md(ptr %addr) {555; CHECK-LABEL: @atomic_sub_zero_volatile_preserve_md(556; CHECK-NEXT: [[RES:%.*]] = atomicrmw volatile sub ptr [[ADDR:%.*]], i64 0 acquire, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]557; CHECK-NEXT: ret i64 [[RES]]558;559 %res = atomicrmw volatile sub ptr %addr, i64 0 acquire, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1560 ret i64 %res561}562 563 564; Check that the transformation properly preserve the syncscope.565; Idempotent atomicrmw are still canonicalized.566define i16 @atomic_syncscope_preserve_md(ptr %addr) {567; CHECK-LABEL: @atomic_syncscope_preserve_md(568; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 syncscope("some_syncscope") acquire, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]569; CHECK-NEXT: ret i16 [[RES]]570;571 %res = atomicrmw or ptr %addr, i16 0 syncscope("some_syncscope") acquire, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1572 ret i16 %res573}574 575; By eliminating the store part of the atomicrmw, we would get rid of the576; release semantic, which is incorrect. We can canonicalize the operation.577define i16 @atomic_seq_cst_preserve_md(ptr %addr) {578; CHECK-LABEL: @atomic_seq_cst_preserve_md(579; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 seq_cst, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]580; CHECK-NEXT: ret i16 [[RES]]581;582 %res = atomicrmw add ptr %addr, i16 0 seq_cst, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1583 ret i16 %res584}585 586; Check that the transformation does not apply when the value is changed by587; the atomic operation (non zero constant).588define i16 @atomic_add_non_zero_preserve_md(ptr %addr) {589; CHECK-LABEL: @atomic_add_non_zero_preserve_md(590; CHECK-NEXT: [[RES:%.*]] = atomicrmw add ptr [[ADDR:%.*]], i16 2 syncscope("agent") monotonic, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]591; CHECK-NEXT: ret i16 [[RES]]592;593 %res = atomicrmw add ptr %addr, i16 2 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1594 ret i16 %res595}596 597; Idempotent atomicrmw are still canonicalized.598define i16 @atomic_xor_zero_preserve_md(ptr %addr) {599; CHECK-LABEL: @atomic_xor_zero_preserve_md(600; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 syncscope("agent") monotonic, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]601; CHECK-NEXT: ret i16 [[RES]]602;603 %res = atomicrmw xor ptr %addr, i16 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1604 ret i16 %res605}606 607; Check that the transformation does not apply when the ordering is608; incompatible with a load (release). Do canonicalize.609define i16 @atomic_release_preserve_md(ptr %addr) {610; CHECK-LABEL: @atomic_release_preserve_md(611; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 release, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]612; CHECK-NEXT: ret i16 [[RES]]613;614 %res = atomicrmw sub ptr %addr, i16 0 release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1615 ret i16 %res616}617 618; Check that the transformation does not apply when the ordering is619; incompatible with a load (acquire, release). Do canonicalize.620define i16 @atomic_acq_rel_preserve_md(ptr %addr) {621; CHECK-LABEL: @atomic_acq_rel_preserve_md(622; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i16 0 acq_rel, align 2, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]623; CHECK-NEXT: ret i16 [[RES]]624;625 %res = atomicrmw xor ptr %addr, i16 0 acq_rel, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1626 ret i16 %res627}628 629define i32 @sat_or_allones_preserve_md(ptr %addr) {630; CHECK-LABEL: @sat_or_allones_preserve_md(631; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]632; CHECK-NEXT: ret i32 [[RES]]633;634 %res = atomicrmw or ptr %addr, i32 -1 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1635 ret i32 %res636}637 638define i32 @sat_and_zero_preserve_md(ptr %addr) {639; CHECK-LABEL: @sat_and_zero_preserve_md(640; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]641; CHECK-NEXT: ret i32 [[RES]]642;643 %res = atomicrmw and ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1644 ret i32 %res645}646 647define i32 @sat_umin_uint_min_preserve_md(ptr %addr) {648; CHECK-LABEL: @sat_umin_uint_min_preserve_md(649; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]650; CHECK-NEXT: ret i32 [[RES]]651;652 %res = atomicrmw umin ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1653 ret i32 %res654}655 656define i32 @sat_umax_uint_max_preserve_md(ptr %addr) {657; CHECK-LABEL: @sat_umax_uint_max_preserve_md(658; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]659; CHECK-NEXT: ret i32 [[RES]]660;661 %res = atomicrmw umax ptr %addr, i32 -1 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1662 ret i32 %res663}664 665define i8 @sat_min_smin_char_preserve_md(ptr %addr) {666; CHECK-LABEL: @sat_min_smin_char_preserve_md(667; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i8 -128 syncscope("agent") monotonic, align 1, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]668; CHECK-NEXT: ret i8 [[RES]]669;670 %res = atomicrmw min ptr %addr, i8 -128 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1671 ret i8 %res672}673 674define i8 @sat_max_smax_char_preserve_md(ptr %addr) {675; CHECK-LABEL: @sat_max_smax_char_preserve_md(676; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i8 127 syncscope("agent") monotonic, align 1, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]677; CHECK-NEXT: ret i8 [[RES]]678;679 %res = atomicrmw max ptr %addr, i8 127 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1680 ret i8 %res681}682 683define double @sat_fadd_nan_preserve_md(ptr %addr) {684; CHECK-LABEL: @sat_fadd_nan_preserve_md(685; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF release, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]686; CHECK-NEXT: ret double [[RES]]687;688 %res = atomicrmw fadd ptr %addr, double 0x7FF00000FFFFFFFF release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1689 ret double %res690}691 692define double @sat_fsub_nan_preserve_md(ptr %addr) {693; CHECK-LABEL: @sat_fsub_nan_preserve_md(694; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF release, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]695; CHECK-NEXT: ret double [[RES]]696;697 %res = atomicrmw fsub ptr %addr, double 0x7FF00000FFFFFFFF release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1698 ret double %res699}700 701define void @sat_fsub_nan_unused_preserve_md(ptr %addr) {702; CHECK-LABEL: @sat_fsub_nan_unused_preserve_md(703; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF00000FFFFFFFF syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]704; CHECK-NEXT: ret void705;706 atomicrmw fsub ptr %addr, double 0x7FF00000FFFFFFFF syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1707 ret void708}709 710define void @xchg_unused_monotonic_preserve_md(ptr %addr) {711; CHECK-LABEL: @xchg_unused_monotonic_preserve_md(712; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]713; CHECK-NEXT: ret void714;715 atomicrmw xchg ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1716 ret void717}718 719define void @xchg_unused_release_preserve_md(ptr %addr) {720; CHECK-LABEL: @xchg_unused_release_preserve_md(721; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") release, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]722; CHECK-NEXT: ret void723;724 atomicrmw xchg ptr %addr, i32 -1 syncscope("agent") release, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1725 ret void726}727 728define void @xchg_unused_under_aligned_preserve_md(ptr %addr) {729; CHECK-LABEL: @xchg_unused_under_aligned_preserve_md(730; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") release, align 1, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]731; CHECK-NEXT: ret void732;733 atomicrmw xchg ptr %addr, i32 -1 syncscope("agent") release, align 1, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1734 ret void735}736 737define void @xchg_unused_over_aligned_preserve_md(ptr %addr) {738; CHECK-LABEL: @xchg_unused_over_aligned_preserve_md(739; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") release, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]740; CHECK-NEXT: ret void741;742 atomicrmw xchg ptr %addr, i32 -1 syncscope("agent") release, align 8, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1743 ret void744}745 746define void @xchg_unused_seq_cst_preserve_md(ptr %addr) {747; CHECK-LABEL: @xchg_unused_seq_cst_preserve_md(748; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 0 syncscope("agent") seq_cst, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]749; CHECK-NEXT: ret void750;751 atomicrmw xchg ptr %addr, i32 0 syncscope("agent") seq_cst, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1752 ret void753}754 755define void @xchg_unused_volatile_preserve_md(ptr %addr) {756; CHECK-LABEL: @xchg_unused_volatile_preserve_md(757; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw volatile xchg ptr [[ADDR:%.*]], i32 0 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]758; CHECK-NEXT: ret void759;760 atomicrmw volatile xchg ptr %addr, i32 0 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1761 ret void762}763 764define void @sat_or_allones_unused_preserve_md(ptr %addr) {765; CHECK-LABEL: @sat_or_allones_unused_preserve_md(766; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], i32 -1 syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]767; CHECK-NEXT: ret void768;769 atomicrmw or ptr %addr, i32 -1 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1770 ret void771}772 773define void @undef_operand_unused_preserve_md(ptr %addr) {774; CHECK-LABEL: @undef_operand_unused_preserve_md(775; CHECK-NEXT: [[TMP1:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 undef syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]776; CHECK-NEXT: ret void777;778 atomicrmw or ptr %addr, i32 undef syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1779 ret void780}781 782define i32 @undef_operand_used_preserve_md(ptr %addr) {783; CHECK-LABEL: @undef_operand_used_preserve_md(784; CHECK-NEXT: [[RES:%.*]] = atomicrmw or ptr [[ADDR:%.*]], i32 undef syncscope("agent") monotonic, align 4, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]785; CHECK-NEXT: ret i32 [[RES]]786;787 %res = atomicrmw or ptr %addr, i32 undef syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1788 ret i32 %res789}790 791define double @sat_fmax_inf_preserve_md(ptr %addr) {792; CHECK-LABEL: @sat_fmax_inf_preserve_md(793; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0x7FF0000000000000 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]794; CHECK-NEXT: ret double [[RES]]795;796 %res = atomicrmw fmax ptr %addr, double 0x7FF0000000000000 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1797 ret double %res798}799 800define double @no_sat_fmax_inf_preserve_md(ptr %addr) {801; CHECK-LABEL: @no_sat_fmax_inf_preserve_md(802; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmax ptr [[ADDR:%.*]], double 1.000000e-01 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]803; CHECK-NEXT: ret double [[RES]]804;805 %res = atomicrmw fmax ptr %addr, double 1.000000e-01 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1806 ret double %res807}808 809define double @sat_fmin_inf_preserve_md(ptr %addr) {810; CHECK-LABEL: @sat_fmin_inf_preserve_md(811; CHECK-NEXT: [[RES:%.*]] = atomicrmw xchg ptr [[ADDR:%.*]], double 0xFFF0000000000000 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]812; CHECK-NEXT: ret double [[RES]]813;814 %res = atomicrmw fmin ptr %addr, double 0xFFF0000000000000 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1815 ret double %res816}817 818define double @no_sat_fmin_inf_preserve_md(ptr %addr) {819; CHECK-LABEL: @no_sat_fmin_inf_preserve_md(820; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmin ptr [[ADDR:%.*]], double 1.000000e-01 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]821; CHECK-NEXT: ret double [[RES]]822;823 %res = atomicrmw fmin ptr %addr, double 1.000000e-01 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1824 ret double %res825}826 827define double @sat_fmaximum_inf_preserve_md(ptr %addr) {828; CHECK-LABEL: @sat_fmaximum_inf_preserve_md(829; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmaximum ptr [[ADDR:%.*]], double 0x7FF0000000000000 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]830; CHECK-NEXT: ret double [[RES]]831;832 %res = atomicrmw fmaximum ptr %addr, double 0x7FF0000000000000 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1833 ret double %res834}835 836define double @no_sat_fmaximum_inf_preserve_md(ptr %addr) {837; CHECK-LABEL: @no_sat_fmaximum_inf_preserve_md(838; CHECK-NEXT: [[RES:%.*]] = atomicrmw fmaximum ptr [[ADDR:%.*]], double 1.000000e-01 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]839; CHECK-NEXT: ret double [[RES]]840;841 %res = atomicrmw fmaximum ptr %addr, double 1.000000e-01 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1842 ret double %res843}844 845define double @sat_fminimum_inf_preserve_md(ptr %addr) {846; CHECK-LABEL: @sat_fminimum_inf_preserve_md(847; CHECK-NEXT: [[RES:%.*]] = atomicrmw fminimum ptr [[ADDR:%.*]], double 0xFFF0000000000000 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]848; CHECK-NEXT: ret double [[RES]]849;850 %res = atomicrmw fminimum ptr %addr, double 0xFFF0000000000000 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1851 ret double %res852}853 854define double @no_sat_fminimum_inf_preserve_md(ptr %addr) {855; CHECK-LABEL: @no_sat_fminimum_inf_preserve_md(856; CHECK-NEXT: [[RES:%.*]] = atomicrmw fminimum ptr [[ADDR:%.*]], double 1.000000e-01 syncscope("agent") monotonic, align 8, !mmra [[META0]], !amdgpu.no.fine.grained.host.memory [[META1]], !amdgpu.no.remote.memory.access [[META1]]857; CHECK-NEXT: ret double [[RES]]858;859 %res = atomicrmw fminimum ptr %addr, double 1.000000e-01 syncscope("agent") monotonic, !amdgpu.no.fine.grained.host.memory !0, !amdgpu.no.remote.memory.access !0, !mmra !1860 ret double %res861}862 863!0 = !{}864!1 = !{!"foo", !"bar"}865