| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1 @@ | ||
| BasedOnStyle: clang-format |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| // UNSUPPORTED: c++03, c++11, c++14, c++17 | ||
|
|
||
| // <compare>, <iterator>, <ranges> | ||
|
|
||
| // ADL should be performed. Ordinary unqualified lookup should not be performed. | ||
|
|
||
| namespace ns { | ||
| struct StructWithGlobalFunctions {}; | ||
| } // namespace ns | ||
|
|
||
| struct ConvertibleToCmpType; | ||
| ConvertibleToCmpType strong_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); | ||
| ConvertibleToCmpType weak_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); | ||
| ConvertibleToCmpType partial_order(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); | ||
|
|
||
| int&& iter_move(const ns::StructWithGlobalFunctions&); | ||
| void iter_swap(const ns::StructWithGlobalFunctions&, const ns::StructWithGlobalFunctions&); | ||
|
|
||
| int* begin(const ns::StructWithGlobalFunctions&); | ||
| int* end(const ns::StructWithGlobalFunctions&); | ||
| int* rbegin(const ns::StructWithGlobalFunctions&); | ||
| int* rend(const ns::StructWithGlobalFunctions&); | ||
| unsigned int size(const ns::StructWithGlobalFunctions&); | ||
|
|
||
| #include <compare> | ||
| #include <ranges> | ||
| #include <type_traits> | ||
|
|
||
| struct ConvertibleToCmpType { | ||
| operator std::strong_ordering() const; | ||
| operator std::weak_ordering() const; | ||
| operator std::partial_ordering() const; | ||
| }; | ||
|
|
||
| struct StructWithHiddenFriends { | ||
| friend ConvertibleToCmpType strong_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); | ||
| friend ConvertibleToCmpType weak_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); | ||
| friend ConvertibleToCmpType partial_order(const StructWithHiddenFriends&, const StructWithHiddenFriends&); | ||
|
|
||
| friend int&& iter_move(const StructWithHiddenFriends&); | ||
| friend void iter_swap(const StructWithHiddenFriends&, const StructWithHiddenFriends&); | ||
|
|
||
| friend int* begin(const StructWithHiddenFriends&); | ||
| friend int* end(const StructWithHiddenFriends&); | ||
| friend int* rbegin(const StructWithHiddenFriends&); | ||
| friend int* rend(const StructWithHiddenFriends&); | ||
| friend unsigned int size(const StructWithHiddenFriends&); | ||
| }; | ||
|
|
||
| // [cmp.alg] ADL should be performed. | ||
| static_assert(std::is_invocable_v<decltype(std::strong_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::weak_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::partial_order), StructWithHiddenFriends&, StructWithHiddenFriends&>); | ||
|
|
||
| // [cmp.alg] Ordinary unqualified lookup should not be performed. | ||
| static_assert( | ||
| !std::is_invocable_v<decltype(std::strong_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); | ||
| static_assert( | ||
| !std::is_invocable_v<decltype(std::weak_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); | ||
| static_assert( | ||
| !std::is_invocable_v<decltype(std::partial_order), ns::StructWithGlobalFunctions&, ns::StructWithGlobalFunctions&>); | ||
|
|
||
| // [iterator.cust] ADL should be performed. | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::iter_move), StructWithHiddenFriends&>); | ||
| static_assert( | ||
| std::is_invocable_v<decltype(std::ranges::iter_swap), StructWithHiddenFriends&, StructWithHiddenFriends&>); | ||
|
|
||
| // [iterator.cust] Ordinary unqualified lookup should not be performed. | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::iter_move), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::iter_swap), | ||
| ns::StructWithGlobalFunctions&, | ||
| ns::StructWithGlobalFunctions&>); | ||
|
|
||
| // [range.access] ADL should be performed. | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::begin), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::cbegin), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::end), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::cend), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::rbegin), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::crbegin), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::rend), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::crend), StructWithHiddenFriends&>); | ||
| static_assert(std::is_invocable_v<decltype(std::ranges::size), StructWithHiddenFriends&>); | ||
|
|
||
| // [range.access] Ordinary unqualified lookup should not be performed. | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::begin), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::cbegin), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::end), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::cend), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::rbegin), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::crbegin), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::rend), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::crend), ns::StructWithGlobalFunctions&>); | ||
| static_assert(!std::is_invocable_v<decltype(std::ranges::size), ns::StructWithGlobalFunctions&>); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| ; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for clamp are generated for float/int/uint vectors. | ||
|
|
||
| ; CHECK-LABEL: clamp_half3 | ||
| define noundef <3 x half> @clamp_half3(<3 x half> noundef %a, <3 x half> noundef %b, <3 x half> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <3 x half> @llvm.maxnum.v3f16(<3 x half> %a, <3 x half> %b) | ||
| ; CHECK: call <3 x half> @llvm.minnum.v3f16(<3 x half> %{{.*}}, <3 x half> %c) | ||
| %dx.clamp = call <3 x half> @llvm.dx.clamp.v3f16(<3 x half> %a, <3 x half> %b, <3 x half> %c) | ||
| ret <3 x half> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_float4 | ||
| define noundef <4 x float> @clamp_float4(<4 x float> noundef %a, <4 x float> noundef %b, <4 x float> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <4 x float> @llvm.maxnum.v4f32(<4 x float> %a, <4 x float> %b) | ||
| ; CHECK: call <4 x float> @llvm.minnum.v4f32(<4 x float> %{{.*}}, <4 x float> %c) | ||
| %dx.clamp = call <4 x float> @llvm.dx.clamp.v4f32(<4 x float> %a, <4 x float> %b, <4 x float> %c) | ||
| ret <4 x float> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_double2 | ||
| define noundef <2 x double> @clamp_double2(<2 x double> noundef %a, <2 x double> noundef %b, <2 x double> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <2 x double> @llvm.maxnum.v2f64(<2 x double> %a, <2 x double> %b) | ||
| ; CHECK: call <2 x double> @llvm.minnum.v2f64(<2 x double> %{{.*}}, <2 x double> %c) | ||
| %dx.clamp = call <2 x double> @llvm.dx.clamp.v2f64(<2 x double> %a, <2 x double> %b, <2 x double> %c) | ||
| ret <2 x double> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_int4 | ||
| define noundef <4 x i32> @clamp_int4(<4 x i32> noundef %a, <4 x i32> noundef %b, <4 x i32> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %b) | ||
| ; CHECK: call <4 x i32> @llvm.smin.v4i32(<4 x i32> %{{.*}}, <4 x i32> %c) | ||
| %dx.clamp = call <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) | ||
| ret <4 x i32> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_uint16_t3 | ||
| define noundef <3 x i16> @clamp_uint16_t3(<3 x i16> noundef %a, <3 x i16> noundef %b, <3 x i16> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <3 x i16> @llvm.umax.v3i16(<3 x i16> %a, <3 x i16> %b) | ||
| ; CHECK: call <3 x i16> @llvm.umin.v3i16(<3 x i16> %{{.*}}, <3 x i16> %c) | ||
| %dx.clamp = call <3 x i16> @llvm.dx.uclamp.v3i16(<3 x i16> %a, <3 x i16> %b, <3 x i16> %c) | ||
| ret <3 x i16> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_uint4 | ||
| define noundef <4 x i32> @clamp_uint4(<4 x i32> noundef %a, <4 x i32> noundef %b, <4 x i32> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %b) | ||
| ; CHECK: call <4 x i32> @llvm.umin.v4i32(<4 x i32> %{{.*}}, <4 x i32> %c) | ||
| %dx.clamp = call <4 x i32> @llvm.dx.uclamp.v4i32(<4 x i32> %a, <4 x i32> %b, <4 x i32> %c) | ||
| ret <4 x i32> %dx.clamp | ||
| } | ||
|
|
||
| ; CHECK-LABEL: clamp_uint64_t4 | ||
| define noundef <2 x i64> @clamp_uint64_t4(<2 x i64> noundef %a, <2 x i64> noundef %b, <2 x i64> noundef %c) { | ||
| entry: | ||
| ; CHECK: call <2 x i64> @llvm.umax.v2i64(<2 x i64> %a, <2 x i64> %b) | ||
| ; CHECK: call <2 x i64> @llvm.umin.v2i64(<2 x i64> %{{.*}}, <2 x i64> %c) | ||
| %dx.clamp = call <2 x i64> @llvm.dx.uclamp.v2i64(<2 x i64> %a, <2 x i64> %b, <2 x i64> %c) | ||
| ret <2 x i64> %dx.clamp | ||
| } | ||
|
|
||
| declare <3 x half> @llvm.dx.clamp.v3f16(<3 x half>, <3 x half>, <3 x half>) | ||
| declare <4 x float> @llvm.dx.clamp.v4f32(<4 x float>, <4 x float>, <4 x float>) | ||
| declare <2 x double> @llvm.dx.clamp.v2f64(<2 x double>, <2 x double>, <2 x double>) | ||
| declare <4 x i32> @llvm.dx.clamp.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) | ||
| declare <3 x i16> @llvm.dx.uclamp.v3i32(<3 x i16>, <3 x i32>, <3 x i16>) | ||
| declare <4 x i32> @llvm.dx.uclamp.v4i32(<4 x i32>, <4 x i32>, <4 x i32>) | ||
| declare <2 x i64> @llvm.dx.uclamp.v2i64(<2 x i64>, <2 x i64>, <2 x i64>) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for clamp/uclamp are generated for half/float/double/i16/i32/i64. | ||
|
|
||
| ; CHECK-LABEL:test_clamp_i16 | ||
| define noundef i16 @test_clamp_i16(i16 noundef %a, i16 noundef %b, i16 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 37, i16 %{{.*}}, i16 %{{.*}}) | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 38, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.dx.clamp.i16(i16 %a, i16 %b, i16 %c) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_clamp_i32 | ||
| define noundef i32 @test_clamp_i32(i32 noundef %a, i32 noundef %b, i32 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 37, i32 %{{.*}}, i32 %{{.*}}) | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 38, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.dx.clamp.i32(i32 %a, i32 %b, i32 %c) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_clamp_i64 | ||
| define noundef i64 @test_clamp_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 37, i64 %a, i64 %b) | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 38, i64 %{{.*}}, i64 %c) | ||
| %0 = call i64 @llvm.dx.clamp.i64(i64 %a, i64 %b, i64 %c) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_clamp_half | ||
| define noundef half @test_clamp_half(half noundef %a, half noundef %b, half noundef %c) { | ||
| entry: | ||
| ; CHECK: call half @dx.op.binary.f16(i32 35, half %{{.*}}, half %{{.*}}) | ||
| ; CHECK: call half @dx.op.binary.f16(i32 36, half %{{.*}}, half %{{.*}}) | ||
| %0 = call half @llvm.dx.clamp.f16(half %a, half %b, half %c) | ||
| ret half %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_clamp_float | ||
| define noundef float @test_clamp_float(float noundef %a, float noundef %b, float noundef %c) { | ||
| entry: | ||
| ; CHECK: call float @dx.op.binary.f32(i32 35, float %{{.*}}, float %{{.*}}) | ||
| ; CHECK: call float @dx.op.binary.f32(i32 36, float %{{.*}}, float %{{.*}}) | ||
| %0 = call float @llvm.dx.clamp.f32(float %a, float %b, float %c) | ||
| ret float %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_clamp_double | ||
| define noundef double @test_clamp_double(double noundef %a, double noundef %b, double noundef %c) { | ||
| entry: | ||
| ; CHECK: call double @dx.op.binary.f64(i32 35, double %{{.*}}, double %{{.*}}) | ||
| ; CHECK: call double @dx.op.binary.f64(i32 36, double %{{.*}}, double %{{.*}}) | ||
| %0 = call double @llvm.dx.clamp.f64(double %a, double %b, double %c) | ||
| ret double %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_uclamp_i16 | ||
| define noundef i16 @test_uclamp_i16(i16 noundef %a, i16 noundef %b, i16 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 39, i16 %{{.*}}, i16 %{{.*}}) | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 40, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.dx.uclamp.i16(i16 %a, i16 %b, i16 %c) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_uclamp_i32 | ||
| define noundef i32 @test_uclamp_i32(i32 noundef %a, i32 noundef %b, i32 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 39, i32 %{{.*}}, i32 %{{.*}}) | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 40, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.dx.uclamp.i32(i32 %a, i32 %b, i32 %c) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_uclamp_i64 | ||
| define noundef i64 @test_uclamp_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 39, i64 %a, i64 %b) | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 40, i64 %{{.*}}, i64 %c) | ||
| %0 = call i64 @llvm.dx.uclamp.i64(i64 %a, i64 %b, i64 %c) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| declare half @llvm.dx.clamp.f16(half, half, half) | ||
| declare float @llvm.dx.clamp.f32(float, float, float) | ||
| declare double @llvm.dx.clamp.f64(double, double, double) | ||
| declare i16 @llvm.dx.clamp.i16(i16, i16, i16) | ||
| declare i32 @llvm.dx.clamp.i32(i32, i32, i32) | ||
| declare i64 @llvm.dx.clamp.i64(i64, i64, i64) | ||
| declare i16 @llvm.dx.uclamp.i16(i16, i16, i16) | ||
| declare i32 @llvm.dx.uclamp.i32(i32, i32, i32) | ||
| declare i64 @llvm.dx.uclamp.i64(i64, i64, i64) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for fmax are generated for half/float/double. | ||
|
|
||
| ; CHECK-LABEL:test_fmax_half | ||
| define noundef half @test_fmax_half(half noundef %a, half noundef %b) { | ||
| entry: | ||
| ; CHECK: call half @dx.op.binary.f16(i32 35, half %{{.*}}, half %{{.*}}) | ||
| %0 = call half @llvm.maxnum.f16(half %a, half %b) | ||
| ret half %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_fmax_float | ||
| define noundef float @test_fmax_float(float noundef %a, float noundef %b) { | ||
| entry: | ||
| ; CHECK: call float @dx.op.binary.f32(i32 35, float %{{.*}}, float %{{.*}}) | ||
| %0 = call float @llvm.maxnum.f32(float %a, float %b) | ||
| ret float %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_fmax_double | ||
| define noundef double @test_fmax_double(double noundef %a, double noundef %b) { | ||
| entry: | ||
| ; CHECK: call double @dx.op.binary.f64(i32 35, double %{{.*}}, double %{{.*}}) | ||
| %0 = call double @llvm.maxnum.f64(double %a, double %b) | ||
| ret double %0 | ||
| } | ||
|
|
||
| declare half @llvm.maxnum.f16(half, half) | ||
| declare float @llvm.maxnum.f32(float, float) | ||
| declare double @llvm.maxnum.f64(double, double) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for fmin are generated for half/float/double. | ||
|
|
||
| ; CHECK-LABEL:test_fmin_half | ||
| define noundef half @test_fmin_half(half noundef %a, half noundef %b) { | ||
| entry: | ||
| ; CHECK: call half @dx.op.binary.f16(i32 36, half %{{.*}}, half %{{.*}}) | ||
| %0 = call half @llvm.minnum.f16(half %a, half %b) | ||
| ret half %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_fmin_float | ||
| define noundef float @test_fmin_float(float noundef %a, float noundef %b) { | ||
| entry: | ||
| ; CHECK: call float @dx.op.binary.f32(i32 36, float %{{.*}}, float %{{.*}}) | ||
| %0 = call float @llvm.minnum.f32(float %a, float %b) | ||
| ret float %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_fmin_double | ||
| define noundef double @test_fmin_double(double noundef %a, double noundef %b) { | ||
| entry: | ||
| ; CHECK: call double @dx.op.binary.f64(i32 36, double %{{.*}}, double %{{.*}}) | ||
| %0 = call double @llvm.minnum.f64(double %a, double %b) | ||
| ret double %0 | ||
| } | ||
|
|
||
| declare half @llvm.minnum.f16(half, half) | ||
| declare float @llvm.minnum.f32(float, float) | ||
| declare double @llvm.minnum.f64(double, double) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for smax are generated for i16/i32/i64. | ||
|
|
||
| ; CHECK-LABEL:test_smax_i16 | ||
| define noundef i16 @test_smax_i16(i16 noundef %a, i16 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 37, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.smax.i16(i16 %a, i16 %b) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_smax_i32 | ||
| define noundef i32 @test_smax_i32(i32 noundef %a, i32 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 37, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.smax.i32(i32 %a, i32 %b) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_smax_i64 | ||
| define noundef i64 @test_smax_i64(i64 noundef %a, i64 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 37, i64 %{{.*}}, i64 %{{.*}}) | ||
| %0 = call i64 @llvm.smax.i64(i64 %a, i64 %b) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| declare i16 @llvm.smax.i16(i16, i16) | ||
| declare i32 @llvm.smax.i32(i32, i32) | ||
| declare i64 @llvm.smax.i64(i64, i64) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for smin are generated for i16/i32/i64. | ||
|
|
||
| ; CHECK-LABEL:test_smin_i16 | ||
| define noundef i16 @test_smin_i16(i16 noundef %a, i16 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 38, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.smin.i16(i16 %a, i16 %b) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_smin_i32 | ||
| define noundef i32 @test_smin_i32(i32 noundef %a, i32 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 38, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.smin.i32(i32 %a, i32 %b) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_smin_i64 | ||
| define noundef i64 @test_smin_i64(i64 noundef %a, i64 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 38, i64 %{{.*}}, i64 %{{.*}}) | ||
| %0 = call i64 @llvm.smin.i64(i64 %a, i64 %b) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| declare i16 @llvm.smin.i16(i16, i16) | ||
| declare i32 @llvm.smin.i32(i32, i32) | ||
| declare i64 @llvm.smin.i64(i64, i64) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,30 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for umax are generated for i16/i32/i64. | ||
|
|
||
| ; CHECK-LABEL:test_umax_i16 | ||
| define noundef i16 @test_umax_i16(i16 noundef %a, i16 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 39, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.umax.i16(i16 %a, i16 %b) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_umax_i32 | ||
| define noundef i32 @test_umax_i32(i32 noundef %a, i32 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 39, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.umax.i32(i32 %a, i32 %b) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_umax_i64 | ||
| define noundef i64 @test_umax_i64(i64 noundef %a, i64 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 39, i64 %{{.*}}, i64 %{{.*}}) | ||
| %0 = call i64 @llvm.umax.i64(i64 %a, i64 %b) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| declare i16 @llvm.umax.i16(i16, i16) | ||
| declare i32 @llvm.umax.i32(i32, i32) | ||
| declare i64 @llvm.umax.i64(i64, i64) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s | ||
|
|
||
| ; Make sure dxil operation function calls for umin are generated for i16/i32/i64. | ||
|
|
||
| ; CHECK-LABEL:test_umin_i16 | ||
| define noundef i16 @test_umin_i16(i16 noundef %a, i16 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i16 @dx.op.binary.i16(i32 40, i16 %{{.*}}, i16 %{{.*}}) | ||
| %0 = call i16 @llvm.umin.i16(i16 %a, i16 %b) | ||
| ret i16 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_umin_i32 | ||
| define noundef i32 @test_umin_i32(i32 noundef %a, i32 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i32 @dx.op.binary.i32(i32 40, i32 %{{.*}}, i32 %{{.*}}) | ||
| %0 = call i32 @llvm.umin.i32(i32 %a, i32 %b) | ||
| ret i32 %0 | ||
| } | ||
|
|
||
| ; CHECK-LABEL:test_umin_i64 | ||
| define noundef i64 @test_umin_i64(i64 noundef %a, i64 noundef %b) { | ||
| entry: | ||
| ; CHECK: call i64 @dx.op.binary.i64(i32 40, i64 %{{.*}}, i64 %{{.*}}) | ||
| %0 = call i64 @llvm.umin.i64(i64 %a, i64 %b) | ||
| ret i64 %0 | ||
| } | ||
|
|
||
| declare i16 @llvm.umin.i16(i16, i16) | ||
| declare i32 @llvm.umin.i32(i32, i32) | ||
| declare i64 @llvm.umin.i64(i64, i64) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| ; REQUIRES: asserts | ||
| ; RUN: opt -S -passes=dfa-jump-threading %s -debug-only=dfa-jump-threading 2>&1 | FileCheck %s | ||
|
|
||
| ; CHECK-COUNT-3: Exiting early due to unpredictability heuristic. | ||
|
|
||
| @.str.1 = private unnamed_addr constant [3 x i8] c"10\00", align 1 | ||
| @.str.2 = private unnamed_addr constant [3 x i8] c"30\00", align 1 | ||
| @.str.3 = private unnamed_addr constant [3 x i8] c"20\00", align 1 | ||
| @.str.4 = private unnamed_addr constant [3 x i8] c"40\00", align 1 | ||
|
|
||
| define void @test1(i32 noundef %num, i32 noundef %num2) { | ||
| entry: | ||
| br label %while.body | ||
|
|
||
| while.body: ; preds = %entry, %sw.epilog | ||
| %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] | ||
| switch i32 %num.addr.0, label %sw.default [ | ||
| i32 10, label %sw.bb | ||
| i32 30, label %sw.bb1 | ||
| i32 20, label %sw.bb2 | ||
| i32 40, label %sw.bb3 | ||
| ] | ||
|
|
||
| sw.bb: ; preds = %while.body | ||
| %call.i = tail call i32 @bar(ptr noundef nonnull @.str.1) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb1: ; preds = %while.body | ||
| %call.i4 = tail call i32 @bar(ptr noundef nonnull @.str.2) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb2: ; preds = %while.body | ||
| %call.i5 = tail call i32 @bar(ptr noundef nonnull @.str.3) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb3: ; preds = %while.body | ||
| %call.i6 = tail call i32 @bar(ptr noundef nonnull @.str.4) | ||
| %call = tail call noundef i32 @foo() | ||
| %add = add nsw i32 %call, %num2 | ||
| br label %sw.epilog | ||
|
|
||
| sw.default: ; preds = %while.body | ||
| ret void | ||
|
|
||
| sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb | ||
| %num.addr.1 = phi i32 [ %add, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %sw.bb ] | ||
| br label %while.body | ||
| } | ||
|
|
||
|
|
||
| define void @test2(i32 noundef %num, i32 noundef %num2) { | ||
| entry: | ||
| br label %while.body | ||
|
|
||
| while.body: ; preds = %entry, %sw.epilog | ||
| %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] | ||
| switch i32 %num.addr.0, label %sw.default [ | ||
| i32 10, label %sw.epilog | ||
| i32 30, label %sw.bb1 | ||
| i32 20, label %sw.bb2 | ||
| i32 40, label %sw.bb3 | ||
| ] | ||
|
|
||
| sw.bb1: ; preds = %while.body | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb2: ; preds = %while.body | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb3: ; preds = %while.body | ||
| br label %sw.epilog | ||
|
|
||
| sw.default: ; preds = %while.body | ||
| ret void | ||
|
|
||
| sw.epilog: ; preds = %while.body, %sw.bb3, %sw.bb2, %sw.bb1 | ||
| %.str.4.sink = phi ptr [ @.str.4, %sw.bb3 ], [ @.str.3, %sw.bb2 ], [ @.str.2, %sw.bb1 ], [ @.str.1, %while.body ] | ||
| %num.addr.1 = phi i32 [ %num2, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %while.body ] | ||
| %call.i6 = tail call i32 @bar(ptr noundef nonnull %.str.4.sink) | ||
| br label %while.body | ||
| } | ||
|
|
||
|
|
||
| define void @test3(i32 noundef %num, i32 noundef %num2) { | ||
| entry: | ||
| %add = add nsw i32 %num2, 40 | ||
| br label %while.body | ||
|
|
||
| while.body: ; preds = %entry, %sw.epilog | ||
| %num.addr.0 = phi i32 [ %num, %entry ], [ %num.addr.1, %sw.epilog ] | ||
| switch i32 %num.addr.0, label %sw.default [ | ||
| i32 10, label %sw.bb | ||
| i32 30, label %sw.bb1 | ||
| i32 20, label %sw.bb2 | ||
| i32 40, label %sw.bb3 | ||
| ] | ||
|
|
||
| sw.bb: ; preds = %while.body | ||
| %call.i = tail call i32 @bar(ptr noundef nonnull @.str.1) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb1: ; preds = %while.body | ||
| %call.i5 = tail call i32 @bar(ptr noundef nonnull @.str.2) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb2: ; preds = %while.body | ||
| %call.i6 = tail call i32 @bar(ptr noundef nonnull @.str.3) | ||
| br label %sw.epilog | ||
|
|
||
| sw.bb3: ; preds = %while.body | ||
| %call.i7 = tail call i32 @bar(ptr noundef nonnull @.str.4) | ||
| br label %sw.epilog | ||
|
|
||
| sw.default: ; preds = %while.body | ||
| ret void | ||
|
|
||
| sw.epilog: ; preds = %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb | ||
| %num.addr.1 = phi i32 [ %add, %sw.bb3 ], [ 40, %sw.bb2 ], [ 20, %sw.bb1 ], [ 30, %sw.bb ] | ||
| br label %while.body | ||
| } | ||
|
|
||
|
|
||
| declare noundef i32 @foo() | ||
| declare noundef i32 @bar(ptr nocapture noundef readonly) |