From 0e15e09245f56ac1c0276dc03aa8444ecf035a69 Mon Sep 17 00:00:00 2001 From: Adam Yang <31109344+adam-yang@users.noreply.github.com> Date: Thu, 26 Aug 2021 18:39:39 -0700 Subject: [PATCH] Short circuit tests. (#3917) --- .../test/CodeGenHLSL/short-circuit-and.hlsl | 59 ++++++++++++++++++ .../test/CodeGenHLSL/short-circuit-or.hlsl | 60 +++++++++++++++++++ .../CodeGenHLSL/short-circuit-select.hlsl | 59 ++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 tools/clang/test/CodeGenHLSL/short-circuit-and.hlsl create mode 100644 tools/clang/test/CodeGenHLSL/short-circuit-or.hlsl create mode 100644 tools/clang/test/CodeGenHLSL/short-circuit-select.hlsl diff --git a/tools/clang/test/CodeGenHLSL/short-circuit-and.hlsl b/tools/clang/test/CodeGenHLSL/short-circuit-and.hlsl new file mode 100644 index 000000000..95cbef391 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/short-circuit-and.hlsl @@ -0,0 +1,59 @@ +// RUN: %dxc /T ps_6_0 %s -enable-short-circuit /Zi | FileCheck %s +// RUN: %dxc /T ps_6_0 %s | FileCheck %s -check-prefix=NO_SHORT_CIRCUIT + +// Load the two uav handles +// CHECK-DAG: %[[uav_foo:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 128, i1 false) +// CHECK-DAG: %[[uav_bar:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 256, i1 false) + +// First side effect +// CHECK-DAG: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_foo]] + +// LHS: sin(...) != 0 +// CHECK-DAG: %[[sin:.+]] = call float @dx.op.unary.f32(i32 13 +// CHECK: %[[foo_cmp:.+]] = fcmp fast une float %[[sin]] +// CHECK: br i1 %[[foo_cmp]], label %[[true_label:.+]], label %[[false_label:.+]], + +// For AND, if first operand is TRUE, goes to evaluate the second operand +// CHECK: [[true_label]]: + +// Second side effect +// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_bar]] + +// RHS: cos(...) != 0 +// CHECK-DAG: %[[cos:.+]] = call float @dx.op.unary.f32(i32 12 +// CHECK: %[[bar_cmp:.+]] = fcmp fast une float %[[cos]] +// CHECK: br i1 %[[bar_cmp]] +// CHECK-SAME: %[[false_label]] + +// Just check there's no branches. +// NO_SHORT_CIRCUIT-NOT: br i1 %{{.+}} +// NO_SHORT_CIRCUIT-NOT: br label %{{.+}} + +RWBuffer buf_foo : register(u128); +RWBuffer buf_bar : register(u256); +cbuffer cb : register(b0) { + uint write_idx0; + uint write_idx1; + float foo_val; + float bar_val; + bool a, b; +} + +bool foo() { + buf_foo[write_idx0] = foo_val; + return sin(foo_val) != 0; +} + +bool bar() { + buf_bar[write_idx1] = bar_val; + return cos(bar_val) != 0; +} + +[RootSignature("DescriptorTable(SRV(t0,numDescriptors=32)),DescriptorTable(CBV(b0,numDescriptors=32)),DescriptorTable(UAV(u0,numDescriptors=1000))")] +float main() : SV_Target { + float ret = 0; + if (foo() && bar()) { + ret = 1; + } + return ret; +} diff --git a/tools/clang/test/CodeGenHLSL/short-circuit-or.hlsl b/tools/clang/test/CodeGenHLSL/short-circuit-or.hlsl new file mode 100644 index 000000000..4c538052d --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/short-circuit-or.hlsl @@ -0,0 +1,60 @@ +// RUN: %dxc /T ps_6_0 %s -enable-short-circuit /Zi | FileCheck %s +// RUN: %dxc /T ps_6_0 %s | FileCheck %s -check-prefix=NO_SHORT_CIRCUIT + +// Load the two uav handles +// CHECK-DAG: %[[uav_foo:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 128, i1 false) +// CHECK-DAG: %[[uav_bar:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 256, i1 false) + +// First side effect +// CHECK-DAG: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_foo]] + +// LHS: sin(...) != 0 +// CHECK-DAG: %[[sin:.+]] = call float @dx.op.unary.f32(i32 13 +// CHECK: %[[foo_cmp:.+]] = fcmp fast une float %[[sin]] +// CHECK: br i1 %[[foo_cmp]], label %[[true_label:.+]], label %[[false_label:.+]], + +// For OR, if first operand is FALSE, goes to evaluate the second operand +// CHECK: [[false_label]]: + +// Second side effect +// CHECK: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_bar]] + +// RHS: cos(...) != 0 +// CHECK-DAG: %[[cos:.+]] = call float @dx.op.unary.f32(i32 12 +// CHECK: %[[bar_cmp:.+]] = fcmp fast une float %[[cos]] +// CHECK: br i1 %[[bar_cmp]] +// CHECK-SAME: %[[true_label]] + +// Just check there's no branches. +// NO_SHORT_CIRCUIT-NOT: br i1 %{{.+}} +// NO_SHORT_CIRCUIT-NOT: br label %{{.+}} + +RWBuffer buf_foo : register(u128); +RWBuffer buf_bar : register(u256); +cbuffer cb : register(b0) { + uint write_idx0; + uint write_idx1; + float foo_val; + float bar_val; + bool a, b; +} + +bool foo() { + buf_foo[write_idx0] = foo_val; + return sin(foo_val) != 0; +} + +bool bar() { + buf_bar[write_idx1] = bar_val; + return cos(bar_val) != 0; +} + +[RootSignature("DescriptorTable(SRV(t0,numDescriptors=32)),DescriptorTable(CBV(b0,numDescriptors=32)),DescriptorTable(UAV(u0,numDescriptors=1000))")] +float main() : SV_Target { + float ret = 0; + if (foo() || bar()) { + ret = 1; + } + return ret; +} + diff --git a/tools/clang/test/CodeGenHLSL/short-circuit-select.hlsl b/tools/clang/test/CodeGenHLSL/short-circuit-select.hlsl new file mode 100644 index 000000000..bb6c1fc65 --- /dev/null +++ b/tools/clang/test/CodeGenHLSL/short-circuit-select.hlsl @@ -0,0 +1,59 @@ +// RUN: %dxc /T ps_6_0 %s -enable-short-circuit /Zi | FileCheck %s +// RUN: %dxc /T ps_6_0 %s | FileCheck %s -check-prefix=NO_SHORT_CIRCUIT + +// Load the two uav handles +// CHECK-DAG: %[[uav_foo:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 128, i1 false) +// CHECK-DAG: %[[uav_bar:.+]] = call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 1, i32 256, i1 false) + +// Cond: +// CHECK-DAG: %[[tan:.+]] = call float @dx.op.unary.f32(i32 14 +// CHECK: %[[cond_cmp:.+]] = fcmp fast une float %[[tan]], 0.000000e+00 + +// The actual select +// CHECK: br i1 %[[cond_cmp]], label %[[true_label:.+]], label %[[false_label:.+]], + +// CHECK: [[true_label]]: +// First side effect +// CHECK-DAG: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_foo]] +// CHECK-DAG: %[[sin:.+]] = call float @dx.op.unary.f32(i32 13 +// CHECK: br label %[[final_block:.+]], + +// CHECK: [[false_label]]: +// Second side effect +// CHECK-DAG: call void @dx.op.bufferStore.f32(i32 69, %dx.types.Handle %[[uav_bar]] +// CHECK-DAG: %[[cos:.+]] = call float @dx.op.unary.f32(i32 12 +// CHECK: br label %[[final_block]], + +// CHECK: [[final_block]]: +// CHECK: phi float [ %[[sin]], %[[true_label]] ], [ %[[cos]], %[[false_label]] ] + +// Just check there's no branches. +// NO_SHORT_CIRCUIT-NOT: br i1 %{{.+}} +// NO_SHORT_CIRCUIT-NOT: br label %{{.+}} + +RWBuffer buf_foo : register(u128); +RWBuffer buf_bar : register(u256); +cbuffer cb : register(b0) { + uint write_idx0; + uint write_idx1; + float foo_val; + float bar_val; + float cond; + bool a, b; +} + +float foo() { + buf_foo[write_idx0] = foo_val; + return sin(foo_val); +} + +float bar() { + buf_bar[write_idx1] = bar_val; + return cos(bar_val); +} + +[RootSignature("DescriptorTable(SRV(t0,numDescriptors=32)),DescriptorTable(CBV(b0,numDescriptors=32)),DescriptorTable(UAV(u0,numDescriptors=1000))")] +float main() : SV_Target { + return tan(cond) != 0 ? foo() : bar(); +} +