
Summary: It's extremely common to conditionally blend two vectors. Previously this was done with mask registers, which is what the normal ternary code generation does when used on a vector. However, since Clang 15 we have supported boolean vector types in the compiler. These are useful in general for checking the mask registers, but are currently limited because they do not map to an LLVM-IR select instruction. This patch simply relaxes these checks, which are technically forbidden by the OpenCL standard. However, general vector support should be able to handle these. We already support this for Arm SVE types, so this should be make more consistent with the clang vector type.
224 lines
11 KiB
C++
224 lines
11 KiB
C++
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
|
|
// RUN: %clang_cc1 -fclang-abi-compat=latest -triple aarch64-none-linux-gnu -target-feature +sve \
|
|
// RUN: -disable-O0-optnone \
|
|
// RUN: -emit-llvm -o - %s | opt -S -passes=sroa | FileCheck %s
|
|
|
|
// REQUIRES: aarch64-registered-target
|
|
|
|
#include <arm_sve.h>
|
|
|
|
// CHECK-LABEL: @_Z9cond_boolu10__SVBool_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 16 x i1> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 16 x i1> [[CMP]], <vscale x 16 x i1> [[A]], <vscale x 16 x i1> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 16 x i1> [[VECTOR_SELECT]]
|
|
//
|
|
svbool_t cond_bool(svbool_t a, svbool_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z7cond_i8u10__SVInt8_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 16 x i8> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 16 x i1> [[CMP]] to <vscale x 16 x i8>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 16 x i8> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 16 x i1> [[VECTOR_COND]], <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 16 x i8> [[VECTOR_SELECT]]
|
|
//
|
|
svint8_t cond_i8(svint8_t a, svint8_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z7cond_u8u11__SVUint8_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 16 x i8> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 16 x i1> [[CMP]] to <vscale x 16 x i8>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 16 x i8> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 16 x i1> [[VECTOR_COND]], <vscale x 16 x i8> [[A]], <vscale x 16 x i8> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 16 x i8> [[VECTOR_SELECT]]
|
|
//
|
|
svuint8_t cond_u8(svuint8_t a, svuint8_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_i16u11__SVInt16_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 8 x i16> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 8 x i1> [[CMP]] to <vscale x 8 x i16>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 8 x i16> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 8 x i1> [[VECTOR_COND]], <vscale x 8 x i16> [[A]], <vscale x 8 x i16> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 8 x i16> [[VECTOR_SELECT]]
|
|
//
|
|
svint16_t cond_i16(svint16_t a, svint16_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_u16u12__SVUint16_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 8 x i16> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 8 x i1> [[CMP]] to <vscale x 8 x i16>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 8 x i16> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 8 x i1> [[VECTOR_COND]], <vscale x 8 x i16> [[A]], <vscale x 8 x i16> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 8 x i16> [[VECTOR_SELECT]]
|
|
//
|
|
svuint16_t cond_u16(svuint16_t a, svuint16_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_i32u11__SVInt32_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 4 x i32> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 4 x i32> [[VECTOR_SELECT]]
|
|
//
|
|
svint32_t cond_i32(svint32_t a, svint32_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_u32u12__SVUint32_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 4 x i32> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 4 x i32> [[VECTOR_SELECT]]
|
|
//
|
|
svuint32_t cond_u32(svuint32_t a, svuint32_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_i64u11__SVInt64_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 2 x i64> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x i64> [[A]], <vscale x 2 x i64> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 2 x i64> [[VECTOR_SELECT]]
|
|
//
|
|
svint64_t cond_i64(svint64_t a, svint64_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_u64u12__SVUint64_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 2 x i64> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x i64> [[A]], <vscale x 2 x i64> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 2 x i64> [[VECTOR_SELECT]]
|
|
//
|
|
svuint64_t cond_u64(svuint64_t a, svuint64_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_f16u13__SVFloat16_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <vscale x 8 x half> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 8 x i1> [[CMP]] to <vscale x 8 x i16>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 8 x i16> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 8 x i1> [[VECTOR_COND]], <vscale x 8 x half> [[A]], <vscale x 8 x half> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 8 x half> [[VECTOR_SELECT]]
|
|
//
|
|
svfloat16_t cond_f16(svfloat16_t a, svfloat16_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_f32u13__SVFloat32_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <vscale x 4 x float> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x float> [[A]], <vscale x 4 x float> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 4 x float> [[VECTOR_SELECT]]
|
|
//
|
|
svfloat32_t cond_f32(svfloat32_t a, svfloat32_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z8cond_f64u13__SVFloat64_tS_(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <vscale x 2 x double> [[A:%.*]], [[B:%.*]]
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x double> [[A]], <vscale x 2 x double> [[B]]
|
|
// CHECK-NEXT: ret <vscale x 2 x double> [[VECTOR_SELECT]]
|
|
//
|
|
svfloat64_t cond_f64(svfloat64_t a, svfloat64_t b) {
|
|
return a < b ? a : b;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_i32_splatu11__SVInt32_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 4 x i32> [[A:%.*]], zeroinitializer
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> zeroinitializer
|
|
// CHECK-NEXT: ret <vscale x 4 x i32> [[VECTOR_SELECT]]
|
|
//
|
|
svint32_t cond_i32_splat(svint32_t a) {
|
|
return a < 0 ? a : 0;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_u32_splatu12__SVUint32_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 4 x i32> [[A:%.*]], splat (i32 1)
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x i32> [[A]], <vscale x 4 x i32> splat (i32 1)
|
|
// CHECK-NEXT: ret <vscale x 4 x i32> [[VECTOR_SELECT]]
|
|
//
|
|
svuint32_t cond_u32_splat(svuint32_t a) {
|
|
return a < 1u ? a : 1u;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_i64_splatu11__SVInt64_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 2 x i64> [[A:%.*]], zeroinitializer
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x i64> [[A]], <vscale x 2 x i64> zeroinitializer
|
|
// CHECK-NEXT: ret <vscale x 2 x i64> [[VECTOR_SELECT]]
|
|
//
|
|
svint64_t cond_i64_splat(svint64_t a) {
|
|
return a < 0l ? a : 0l;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_u64_splatu12__SVUint64_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = icmp ult <vscale x 2 x i64> [[A:%.*]], splat (i64 1)
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x i64> [[A]], <vscale x 2 x i64> splat (i64 1)
|
|
// CHECK-NEXT: ret <vscale x 2 x i64> [[VECTOR_SELECT]]
|
|
//
|
|
svuint64_t cond_u64_splat(svuint64_t a) {
|
|
return a < 1ul ? a : 1ul;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_f32_splatu13__SVFloat32_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <vscale x 4 x float> [[A:%.*]], zeroinitializer
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 4 x i1> [[CMP]] to <vscale x 4 x i32>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 4 x i32> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 4 x i1> [[VECTOR_COND]], <vscale x 4 x float> [[A]], <vscale x 4 x float> zeroinitializer
|
|
// CHECK-NEXT: ret <vscale x 4 x float> [[VECTOR_SELECT]]
|
|
//
|
|
svfloat32_t cond_f32_splat(svfloat32_t a) {
|
|
return a < 0.f ? a : 0.f;
|
|
}
|
|
|
|
// CHECK-LABEL: @_Z14cond_f64_splatu13__SVFloat64_t(
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[CMP:%.*]] = fcmp olt <vscale x 2 x double> [[A:%.*]], zeroinitializer
|
|
// CHECK-NEXT: [[CONV:%.*]] = zext <vscale x 2 x i1> [[CMP]] to <vscale x 2 x i64>
|
|
// CHECK-NEXT: [[VECTOR_COND:%.*]] = icmp ne <vscale x 2 x i64> [[CONV]], zeroinitializer
|
|
// CHECK-NEXT: [[VECTOR_SELECT:%.*]] = select <vscale x 2 x i1> [[VECTOR_COND]], <vscale x 2 x double> [[A]], <vscale x 2 x double> zeroinitializer
|
|
// CHECK-NEXT: ret <vscale x 2 x double> [[VECTOR_SELECT]]
|
|
//
|
|
svfloat64_t cond_f64_splat(svfloat64_t a) {
|
|
return a < 0. ? a : 0.;
|
|
}
|
|
|