blob: d85be5ca8199364af7490af88fc7dab02e41f64d [file] [edit]
; RUN: opt -S -dxil-resource-type -dxil-resource-access \
; RUN: -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
; Regression test for a loop-carried resource pointer. Walking backwards from
; the load encounters the self-referential incoming value of %ptr.
@Buffer.str = internal unnamed_addr constant [7 x i8] c"Buffer\00"
; CHECK-LABEL: define i32 @loop_carried_pointer_phi(
; CHECK: call { i32, i1 } @llvm.dx.resource.load.rawbuffer
define i32 @loop_carried_pointer_phi(i1 %select, i32 %index, i32 %count) {
entry:
%handle0 = call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding(i32 2, i32 0, i32 2, i32 0, ptr @Buffer.str)
%base0 = call ptr @llvm.dx.resource.getpointer(target("dx.RawBuffer", i32, 1, 0) %handle0, i32 %index)
%handle1 = call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding(i32 2, i32 0, i32 2, i32 1, ptr @Buffer.str)
%base1 = call ptr @llvm.dx.resource.getpointer(target("dx.RawBuffer", i32, 1, 0) %handle1, i32 %index)
br i1 %select, label %left, label %right
left:
br label %loop
right:
br label %loop
loop:
%ptr = phi ptr [ %base0, %left ], [ %base1, %right ], [ %ptr, %loop ]
%i = phi i32 [ 0, %left ], [ 0, %right ], [ %inc, %loop ]
%value = load i32, ptr %ptr, align 4
%inc = add nuw i32 %i, 1
%done = icmp eq i32 %inc, %count
br i1 %done, label %exit, label %loop
exit:
ret i32 %value
}
; An inner phi that only forwards the outer loop-carried phi caches the outer
; phi's placeholder indices. When those placeholders fold away, the cached
; entry must follow them so the later load from %q sees the final indices.
; CHECK-LABEL: define i32 @nested_pointer_phi(
; CHECK: head:
; CHECK-NEXT: %[[IDX:.*]] = phi i32 [ 0, %l ], [ 1, %r ], [ %[[IDX]], %latch ]
; CHECK: latch:
; CHECK-NEXT: %[[HANDLE:.*]] = call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_i32_1_0t(i32 2, i32 0, i32 2, i32 %[[IDX]], ptr @Buffer.str)
; CHECK-NEXT: call { i32, i1 } @llvm.dx.resource.load.rawbuffer.i32.tdx.RawBuffer_i32_1_0t(target("dx.RawBuffer", i32, 1, 0) %[[HANDLE]], i32 %index, i32 0)
define i32 @nested_pointer_phi(i1 %c, i1 %d, i32 %index, i32 %n) {
entry:
%h0 = call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding(i32 2, i32 0, i32 2, i32 0, ptr @Buffer.str)
%b0 = call ptr @llvm.dx.resource.getpointer(target("dx.RawBuffer", i32, 1, 0) %h0, i32 %index)
%h1 = call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefromimplicitbinding(i32 2, i32 0, i32 2, i32 1, ptr @Buffer.str)
%b1 = call ptr @llvm.dx.resource.getpointer(target("dx.RawBuffer", i32, 1, 0) %h1, i32 %index)
br i1 %c, label %l, label %r
l:
br label %head
r:
br label %head
head:
%p = phi ptr [ %b0, %l ], [ %b1, %r ], [ %q, %latch ]
%v0 = load i32, ptr %p, align 4
br i1 %d, label %a, label %b
a:
br label %latch
b:
br label %latch
latch:
%q = phi ptr [ %p, %a ], [ %p, %b ]
%v1 = load i32, ptr %q, align 4
%s = add i32 %v0, %v1
%done = icmp eq i32 %s, %n
br i1 %done, label %exit, label %head
exit:
ret i32 %s
}