blob: afa2342d025c7c27785bf305bb88cd5927fdd00e [file]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --filter "^\s*(?:mov\.b64|ld(?:\.[A-Za-z0-9_:]+)*\.global|st(?:\.[A-Za-z0-9_:]+)*\.global|atom(?:\.[A-Za-z0-9_:]+)*\.global|ld\.param\.b32)" --version 6
; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_80 -mattr=+ptx74 | FileCheck %s --check-prefixes=CHECK,O2
; RUN: llc < %s -mtriple=nvptx64 -mcpu=sm_80 -mattr=+ptx74 -O0 | FileCheck %s --check-prefixes=CHECK,O0
; RUN: %if ptxas-sm_80 && ptxas-isa-7.4 %{ llc < %s -mtriple=nvptx64 -mcpu=sm_80 -mattr=+ptx74 | %ptxas-verify -arch=sm_80 %}
; Test cache hint handling across shared pointers, CSE, forwarding, and legalization.
;-----------------------------------------------------------------------------
; Multiple loads sharing same pointer
;-----------------------------------------------------------------------------
; Non-volatile loads can CSE. Matching cache hints are preserved on the merged
; DAG node, but conflicting hints are dropped.
define i32 @test_cse_loads_same_cache_hint(ptr addrspace(1) %p) {
; CHECK-LABEL: test_cse_loads_same_cache_hint(
; CHECK: ld.global.L1::evict_first.b32 %r1, [%rd1];
%v1 = load i32, ptr addrspace(1) %p, !mem.cache_hint !2
%v2 = load i32, ptr addrspace(1) %p, !mem.cache_hint !2
%sum = add i32 %v1, %v2
ret i32 %sum
}
define i32 @test_cse_loads_conflicting_cache_hints(ptr addrspace(1) %p) {
; CHECK-LABEL: test_cse_loads_conflicting_cache_hints(
; CHECK: ld.global.b32 %r1, [%rd1];
%v1 = load i32, ptr addrspace(1) %p, !mem.cache_hint !2
%v2 = load i32, ptr addrspace(1) %p, !mem.cache_hint !3
%sum = add i32 %v1, %v2
ret i32 %sum
}
; NVPTXForwardParams rewrites eligible byval loads to ld.param. Since cache
; hints are not allowed on ld.param, we must drop them.
define i32 @test_forward_param_drops_l1_hint(ptr byval(i32) %a) {
; CHECK-LABEL: test_forward_param_drops_l1_hint(
; CHECK: ld.param.b32 %r1, [test_forward_param_drops_l1_hint_param_0];
%v = load i32, ptr %a, !mem.cache_hint !4
ret i32 %v
}
define i32 @test_forward_param_drops_l2_cache_hint(ptr byval(i32) %a) {
; CHECK-LABEL: test_forward_param_drops_l2_cache_hint(
; CHECK: ld.param.b32 %r1, [test_forward_param_drops_l2_cache_hint_param_0];
%v = load i32, ptr %a, !mem.cache_hint !5
ret i32 %v
}
;-----------------------------------------------------------------------------
; Valid edge cases
;-----------------------------------------------------------------------------
; Test with custom hint key order - should still work
define i32 @test_load_reordered_metadata(ptr addrspace(1) %p) {
; CHECK-LABEL: test_load_reordered_metadata(
; CHECK: ld.global.L1::evict_last.b32 %r1, [%rd1];
%v = load i32, ptr addrspace(1) %p, !mem.cache_hint !6
ret i32 %v
}
;-----------------------------------------------------------------------------
; nvvm.l2_cache_hint with alternate integer value width
;-----------------------------------------------------------------------------
; nvvm.l2_cache_hint with i32 instead of i64 - should still work
; as mdconst::dyn_extract<ConstantInt> accepts any integer type
define i32 @test_load_cache_hint_i32_value(ptr addrspace(1) %p) {
; CHECK-LABEL: test_load_cache_hint_i32_value(
; CHECK: mov.b64 %rd2, 12345;
; CHECK: ld.global.L2::cache_hint.b32 %r1, [%rd1], %rd2;
%v = load i32, ptr addrspace(1) %p, !mem.cache_hint !7
ret i32 %v
}
; Test "normal" eviction - should not emit any qualifier (default behavior)
define i32 @test_load_l1_normal(ptr addrspace(1) %p) {
; CHECK-LABEL: test_load_l1_normal(
; CHECK: ld.global.b32 %r1, [%rd1];
%v = load i32, ptr addrspace(1) %p, !mem.cache_hint !8
ret i32 %v
}
define i32 @test_load_l2_normal(ptr addrspace(1) %p) {
; CHECK-LABEL: test_load_l2_normal(
; CHECK: ld.global.b32 %r1, [%rd1];
%v = load i32, ptr addrspace(1) %p, !mem.cache_hint !9
ret i32 %v
}
;-----------------------------------------------------------------------------
; TODO: Preserve cache hints across DAGCombiner-created memory rewrites.
; This documents the current store-of-concat-trunc behavior: copied MMOs for
; the split stores do not retain !mem.cache_hint metadata yet.
;-----------------------------------------------------------------------------
define void @test_dagcombine_store_concat_trunc_v8i32(ptr addrspace(1) %p, <4 x i64> %a, <4 x i64> %b) {
; CHECK-LABEL: test_dagcombine_store_concat_trunc_v8i32(
; CHECK: st.global.v4.b32 [%rd1+16], {%r8, %r7, %r6, %r5};
; CHECK: st.global.v4.b32 [%rd1], {%r4, %r3, %r2, %r1};
%ta = trunc <4 x i64> %a to <4 x i32>
%tb = trunc <4 x i64> %b to <4 x i32>
%c = shufflevector <4 x i32> %ta, <4 x i32> %tb, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
store <8 x i32> %c, ptr addrspace(1) %p, align 16, !mem.cache_hint !10
ret void
}
;-----------------------------------------------------------------------------
; TODO: Preserve cache hints across one-to-N DAG memory rewrites.
; These tests document the current split/scalarized behavior: newly-created
; memory ops do not retain !mem.cache_hint metadata yet.
;-----------------------------------------------------------------------------
define <16 x i32> @test_legalize_split_load_v16i32(ptr addrspace(1) %p) {
; O2-LABEL: test_legalize_split_load_v16i32(
; O2: ld.global.v4.b32 {%r1, %r2, %r3, %r4}, [%rd1];
; O2: ld.global.v4.b32 {%r5, %r6, %r7, %r8}, [%rd1+16];
; O2: ld.global.v4.b32 {%r9, %r10, %r11, %r12}, [%rd1+32];
; O2: ld.global.v4.b32 {%r13, %r14, %r15, %r16}, [%rd1+48];
;
; O0-LABEL: test_legalize_split_load_v16i32(
; O0: ld.global.v4.b32 {%r1, %r2, %r3, %r4}, [%rd1+48];
; O0: ld.global.v4.b32 {%r5, %r6, %r7, %r8}, [%rd1+32];
; O0: ld.global.v4.b32 {%r9, %r10, %r11, %r12}, [%rd1+16];
; O0: ld.global.v4.b32 {%r13, %r14, %r15, %r16}, [%rd1];
%v = load <16 x i32>, ptr addrspace(1) %p, align 16, !mem.cache_hint !11
ret <16 x i32> %v
}
define void @test_legalize_split_store_v16i32(ptr addrspace(1) %p, <16 x i32> %v) {
; O2-LABEL: test_legalize_split_store_v16i32(
; O2: st.global.v4.b32 [%rd1+48], {%r1, %r2, %r3, %r4};
; O2: st.global.v4.b32 [%rd1+32], {%r5, %r6, %r7, %r8};
; O2: st.global.v4.b32 [%rd1+16], {%r9, %r10, %r11, %r12};
; O2: st.global.v4.b32 [%rd1], {%r13, %r14, %r15, %r16};
;
; O0-LABEL: test_legalize_split_store_v16i32(
; O0: st.global.v4.b32 [%rd1+48], {%r13, %r14, %r15, %r16};
; O0: st.global.v4.b32 [%rd1+32], {%r9, %r10, %r11, %r12};
; O0: st.global.v4.b32 [%rd1+16], {%r5, %r6, %r7, %r8};
; O0: st.global.v4.b32 [%rd1], {%r1, %r2, %r3, %r4};
store <16 x i32> %v, ptr addrspace(1) %p, align 16, !mem.cache_hint !12
ret void
}
define <3 x i64> @test_legalize_scalarize_load_v3i64(ptr addrspace(1) %p) {
; CHECK-LABEL: test_legalize_scalarize_load_v3i64(
; CHECK: ld.global.b64 %rd2, [%rd1+16];
; CHECK: ld.global.b64 %rd3, [%rd1+8];
; CHECK: ld.global.b64 %rd4, [%rd1];
%v = load <3 x i64>, ptr addrspace(1) %p, align 8, !mem.cache_hint !13
ret <3 x i64> %v
}
define void @test_legalize_scalarize_store_v3i64(ptr addrspace(1) %p, <3 x i64> %v) {
; O2-LABEL: test_legalize_scalarize_store_v3i64(
; O2: st.global.b64 [%rd1+16], %rd2;
; O2: st.global.b64 [%rd1+8], %rd4;
; O2: st.global.b64 [%rd1], %rd3;
;
; O0-LABEL: test_legalize_scalarize_store_v3i64(
; O0: st.global.b64 [%rd1+16], %rd4;
; O0: st.global.b64 [%rd1+8], %rd3;
; O0: st.global.b64 [%rd1], %rd2;
store <3 x i64> %v, ptr addrspace(1) %p, align 8, !mem.cache_hint !14
ret void
}
;-----------------------------------------------------------------------------
; Metadata definitions
;-----------------------------------------------------------------------------
!0 = !{i32 0, !15}
!15 = !{!"nvvm.l2_cache_hint", i64 12345, !"nvvm.l1_eviction", !"last"}
!1 = !{i32 0, !16}
!16 = !{!"nvvm.l2_cache_hint", i64 12345, !"nvvm.l1_eviction", !"first"}
!2 = !{i32 0, !17}
!17 = !{!"nvvm.l1_eviction", !"first"}
!3 = !{i32 0, !18}
!18 = !{!"nvvm.l1_eviction", !"last"}
!4 = !{i32 0, !19}
!19 = !{!"nvvm.l1_eviction", !"first"}
!5 = !{i32 0, !20}
!20 = !{!"nvvm.l2_cache_hint", i64 12345}
!6 = !{i32 0, !21}
!21 = !{!"nvvm.l1_eviction", !"last", !"nvvm.l2_eviction", !"first"}
!7 = !{i32 0, !22}
!22 = !{!"nvvm.l2_cache_hint", i32 12345}
!8 = !{i32 0, !23}
!23 = !{!"nvvm.l1_eviction", !"normal"}
!9 = !{i32 0, !24}
!24 = !{!"nvvm.l2_eviction", !"normal"}
!10 = !{i32 1, !25}
!25 = !{!"nvvm.l2_cache_hint", i64 12345}
!11 = !{i32 0, !26}
!26 = !{!"nvvm.l2_cache_hint", i64 12345}
!12 = !{i32 1, !27}
!27 = !{!"nvvm.l2_cache_hint", i64 12345}
!13 = !{i32 0, !28}
!28 = !{!"nvvm.l1_eviction", !"last"}
!14 = !{i32 1, !29}
!29 = !{!"nvvm.l2_eviction", !"first"}