;=========================== begin_copyright_notice ============================
;
; Copyright (C) 2024 Intel Corporation
;
; SPDX-License-Identifier: MIT
;
;============================ end_copyright_notice =============================
; REQUIRES: llvm-14-plus, debug

; RUN: igc_opt --opaque-pointers --igc-wi-analysis -S < %s 2>&1 | FileCheck %s
; ------------------------------------------------
; WIAnalysis
; ------------------------------------------------

; This test checks optional warning message for non-uniform OpGroupBroadcast.

; LLVM IR reduced from OpenCL test kernels:

; __kernel void test_uniform(global int *dst, int src)
; {
;     dst[0] = sub_group_broadcast(src, 0);
; }

; __kernel void test_nonuniform(global int *dst, int src)
; {
;     dst[0] = sub_group_broadcast(src, get_global_id(0));
; }


; CHECK-NOT: Detected llvm.genx.GenISA.WaveBroadcast{{.*}}kernel test_uniform
; CHECK:     Detected llvm.genx.GenISA.WaveBroadcast{{.*}}kernel test_nonuniform

; Function Attrs: convergent nounwind
define spir_kernel void @test_uniform(i32 addrspace(1)* %dst, i32 %src, <8 x i32> %r0, <8 x i32> %payloadHeader, i32 %bufferOffset) {
entry:
  %simdBroadcast = call i32 @llvm.genx.GenISA.WaveBroadcast.i32(i32 %src, i32 0, i32 0)
  store i32 %simdBroadcast, i32 addrspace(1)* %dst, align 4
  ret void
}

; Function Attrs: convergent nounwind
define spir_kernel void @test_nonuniform(i32 addrspace(1)* %dst, i32 %src, <8 x i32> %r0, <8 x i32> %payloadHeader, <3 x i32> %enqueuedLocalSize, i16 %localIdX, i16 %localIdY, i16 %localIdZ, i32 %bufferOffset) {
entry:
  %0 = extractelement <8 x i32> %payloadHeader, i32 0
  %1 = extractelement <8 x i32> %payloadHeader, i32 1
  %2 = extractelement <8 x i32> %payloadHeader, i32 2
  %3 = extractelement <8 x i32> %payloadHeader, i32 3
  %4 = extractelement <8 x i32> %payloadHeader, i32 4
  %5 = extractelement <8 x i32> %payloadHeader, i32 5
  %6 = extractelement <8 x i32> %payloadHeader, i32 6
  %7 = extractelement <8 x i32> %payloadHeader, i32 7
  %8 = extractelement <3 x i32> %enqueuedLocalSize, i32 0
  %9 = extractelement <3 x i32> %enqueuedLocalSize, i32 1
  %10 = extractelement <3 x i32> %enqueuedLocalSize, i32 2
  %11 = extractelement <8 x i32> %r0, i32 0
  %12 = extractelement <8 x i32> %r0, i32 1
  %13 = extractelement <8 x i32> %r0, i32 2
  %14 = extractelement <8 x i32> %r0, i32 3
  %15 = extractelement <8 x i32> %r0, i32 4
  %16 = extractelement <8 x i32> %r0, i32 5
  %17 = extractelement <8 x i32> %r0, i32 6
  %18 = extractelement <8 x i32> %r0, i32 7
  %mul.i.i.i = mul i32 %8, %12
  %localIdX2 = zext i16 %localIdX to i32
  %add.i.i.i = add i32 %mul.i.i.i, %localIdX2
  %add4.i.i.i = add i32 %add.i.i.i, %0
  %simdBroadcast = call i32 @llvm.genx.GenISA.WaveBroadcast.i32(i32 %src, i32 %add4.i.i.i, i32 0)
  store i32 %simdBroadcast, i32 addrspace(1)* %dst, align 4
  ret void
}

; Function Desc: Broadcasts from specific lane to all lanes. Overlaps with WaveShuffleIndex, but guarantees that lane is thread-uniform.
; Output: result
; Arg 0: value
; Arg 1: lane
; Arg 2: helperLaneMode - to match WaveShuffleIndex
; Function Attrs: convergent nounwind readnone
declare i32 @llvm.genx.GenISA.WaveBroadcast.i32(i32, i32, i32)

!igc.functions = !{!358, !366}

!358 = !{void (i32 addrspace(1)*, i32, <8 x i32>, <8 x i32>, i32)* @test_uniform, !359}
!359 = !{!360}
!360 = !{!"function_type", i32 0}
!366 = !{void (i32 addrspace(1)*, i32, <8 x i32>, <8 x i32>, <3 x i32>, i16, i16, i16, i32)* @test_nonuniform, !367}
!367 = !{!360}
!373 = !{!"argId", i32 0}
!374 = !{!"implicitArgInfoListVec[0]", !373}
!375 = !{!"argId", i32 1}
!376 = !{!"implicitArgInfoListVec[1]", !375}
!377 = !{!"argId", i32 15}
!378 = !{!"explicitArgNum", i32 0}
!379 = !{!"implicitArgInfoListVec[2]", !377, !378}
!380 = !{!"implicitArgInfoList", !374, !376, !379}
!381 = !{!"argId", i32 0}
!382 = !{!"implicitArgInfoListVec[0]", !381}
!383 = !{!"argId", i32 1}
!384 = !{!"implicitArgInfoListVec[1]", !383}
!385 = !{!"argId", i32 7}
!386 = !{!"implicitArgInfoListVec[2]", !385}
!387 = !{!"argId", i32 8}
!388 = !{!"implicitArgInfoListVec[3]", !387}
!389 = !{!"argId", i32 9}
!390 = !{!"implicitArgInfoListVec[4]", !389}
!391 = !{!"argId", i32 10}
!392 = !{!"implicitArgInfoListVec[5]", !391}
!393 = !{!"argId", i32 15}
!394 = !{!"explicitArgNum", i32 0}
!395 = !{!"implicitArgInfoListVec[6]", !393, !394}
!396 = !{!"implicitArgInfoList", !382, !384, !386, !388, !390, !392, !395}
!397 = !{!"FuncMDMap[0]", void (i32 addrspace(1)*, i32, <8 x i32>, <8 x i32>, i32)* @test_uniform}
!398 = !{!"FuncMDValue[0]", !380}
!399 = !{!"FuncMDMap[1]", void (i32 addrspace(1)*, i32, <8 x i32>, <8 x i32>, <3 x i32>, i16, i16, i16, i32)* @test_nonuniform}
!400 = !{!"FuncMDValue[1]", !396}
!401 = !{!"FuncMD", !397, !398, !399, !400}
!402 = !{!"ModuleMD", !401}
!IGCMetadata = !{!402}
