Files
clang-p2996/llvm/test/Transforms/InstCombine/extractelement.ll
Sanjay Patel 535c5d56a7 [InstCombine] ease restriction for extractelt (bitcast X) fold
We were checking for a desirable integer type even when there
is no shift in the transform. This is unnecessary since we
are truncating directly to the destination type.

This removes an extractelt in more cases and seems to make the
canonicalization more uniform overall. There's still a potential
difference between patterns that need a shift vs. trunc-only.

I'm not sure if that is worth keeping at this point, but it can
be adjusted in another step (assuming this change does not cause
trouble).

In the most basic case where I noticed this, we missed a fold
that would have completely removed vector ops from a pattern
like:
https://alive2.llvm.org/ce/z/y4Qdte
2022-11-24 13:27:19 -05:00

905 lines
33 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S -data-layout="e-n64" | FileCheck %s --check-prefixes=ANY,ANYLE,LE64
; RUN: opt < %s -passes=instcombine -S -data-layout="e-n128" | FileCheck %s --check-prefixes=ANY,ANYLE,LE128
; RUN: opt < %s -passes=instcombine -S -data-layout="E-n64" | FileCheck %s --check-prefixes=ANY,ANYBE,BE64
; RUN: opt < %s -passes=instcombine -S -data-layout="E-n128" | FileCheck %s --check-prefixes=ANY,ANYBE,BE128
define i32 @extractelement_out_of_range(<2 x i32> %x) {
; ANY-LABEL: @extractelement_out_of_range(
; ANY-NEXT: ret i32 poison
;
%E1 = extractelement <2 x i32> %x, i8 16
ret i32 %E1
}
define i32 @extractelement_type_out_of_range(<2 x i32> %x) {
; ANY-LABEL: @extractelement_type_out_of_range(
; ANY-NEXT: [[E1:%.*]] = extractelement <2 x i32> [[X:%.*]], i64 0
; ANY-NEXT: ret i32 [[E1]]
;
%E1 = extractelement <2 x i32> %x, i128 0
ret i32 %E1
}
define i32 @bitcasted_inselt_equal_num_elts(float %f) {
; ANY-LABEL: @bitcasted_inselt_equal_num_elts(
; ANY-NEXT: [[R:%.*]] = bitcast float [[F:%.*]] to i32
; ANY-NEXT: ret i32 [[R]]
;
%vf = insertelement <4 x float> undef, float %f, i32 0
%vi = bitcast <4 x float> %vf to <4 x i32>
%r = extractelement <4 x i32> %vi, i32 0
ret i32 %r
}
define i64 @test2(i64 %in) {
; ANY-LABEL: @test2(
; ANY-NEXT: ret i64 [[IN:%.*]]
;
%vec = insertelement <8 x i64> undef, i64 %in, i32 0
%splat = shufflevector <8 x i64> %vec, <8 x i64> undef, <8 x i32> zeroinitializer
%add = add <8 x i64> %splat, <i64 0, i64 1, i64 2, i64 3, i64 4, i64 5, i64 6, i64 7>
%r = extractelement <8 x i64> %add, i32 0
ret i64 %r
}
define i32 @bitcasted_inselt_wide_source_zero_elt(i64 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_zero_elt(
; ANYLE-NEXT: [[R:%.*]] = trunc i64 [[X:%.*]] to i32
; ANYLE-NEXT: ret i32 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_zero_elt(
; ANYBE-NEXT: [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
; ANYBE-NEXT: [[R:%.*]] = trunc i64 [[TMP1]] to i32
; ANYBE-NEXT: ret i32 [[R]]
;
%i = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
%b = bitcast <2 x i64> %i to <4 x i32>
%r = extractelement <4 x i32> %b, i32 0
ret i32 %r
}
define i16 @bitcasted_inselt_wide_source_modulo_elt(i64 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(
; ANYLE-NEXT: [[R:%.*]] = trunc i64 [[X:%.*]] to i16
; ANYLE-NEXT: ret i16 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_modulo_elt(
; ANYBE-NEXT: [[TMP1:%.*]] = lshr i64 [[X:%.*]], 48
; ANYBE-NEXT: [[R:%.*]] = trunc i64 [[TMP1]] to i16
; ANYBE-NEXT: ret i16 [[R]]
;
%i = insertelement <2 x i64> undef, i64 %x, i32 1
%b = bitcast <2 x i64> %i to <8 x i16>
%r = extractelement <8 x i16> %b, i32 4
ret i16 %r
}
define i32 @bitcasted_inselt_wide_source_not_modulo_elt(i64 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(
; ANYLE-NEXT: [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
; ANYLE-NEXT: [[R:%.*]] = trunc i64 [[TMP1]] to i32
; ANYLE-NEXT: ret i32 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt(
; ANYBE-NEXT: [[R:%.*]] = trunc i64 [[X:%.*]] to i32
; ANYBE-NEXT: ret i32 [[R]]
;
%i = insertelement <2 x i64> undef, i64 %x, i32 0
%b = bitcast <2 x i64> %i to <4 x i32>
%r = extractelement <4 x i32> %b, i32 1
ret i32 %r
}
define i8 @bitcasted_inselt_wide_source_not_modulo_elt_not_half(i32 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(
; ANYLE-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 16
; ANYLE-NEXT: [[R:%.*]] = trunc i32 [[TMP1]] to i8
; ANYLE-NEXT: ret i8 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half(
; ANYBE-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 8
; ANYBE-NEXT: [[R:%.*]] = trunc i32 [[TMP1]] to i8
; ANYBE-NEXT: ret i8 [[R]]
;
%i = insertelement <2 x i32> undef, i32 %x, i32 0
%b = bitcast <2 x i32> %i to <8 x i8>
%r = extractelement <8 x i8> %b, i32 2
ret i8 %r
}
define i3 @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(i15 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(
; ANYLE-NEXT: [[TMP1:%.*]] = lshr i15 [[X:%.*]], 3
; ANYLE-NEXT: [[R:%.*]] = trunc i15 [[TMP1]] to i3
; ANYLE-NEXT: ret i3 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_not_modulo_elt_not_half_weird_types(
; ANYBE-NEXT: [[TMP1:%.*]] = lshr i15 [[X:%.*]], 9
; ANYBE-NEXT: [[R:%.*]] = trunc i15 [[TMP1]] to i3
; ANYBE-NEXT: ret i3 [[R]]
;
%i = insertelement <3 x i15> undef, i15 %x, i32 0
%b = bitcast <3 x i15> %i to <15 x i3>
%r = extractelement <15 x i3> %b, i32 1
ret i3 %r
}
; Negative test for the above fold, but we can remove the insert here.
define i8 @bitcasted_inselt_wide_source_wrong_insert(<2 x i32> %v, i32 %x) {
; ANY-LABEL: @bitcasted_inselt_wide_source_wrong_insert(
; ANY-NEXT: [[TMP1:%.*]] = bitcast <2 x i32> [[V:%.*]] to <8 x i8>
; ANY-NEXT: [[R:%.*]] = extractelement <8 x i8> [[TMP1]], i64 2
; ANY-NEXT: ret i8 [[R]]
;
%i = insertelement <2 x i32> %v, i32 %x, i32 1
%b = bitcast <2 x i32> %i to <8 x i8>
%r = extractelement <8 x i8> %b, i32 2
ret i8 %r
}
; Partial negative test for the above fold, extra uses are not allowed if shift is needed.
declare void @use(<8 x i8>)
define i8 @bitcasted_inselt_wide_source_uses(i32 %x) {
; ANYLE-LABEL: @bitcasted_inselt_wide_source_uses(
; ANYLE-NEXT: [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i64 0
; ANYLE-NEXT: [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8>
; ANYLE-NEXT: call void @use(<8 x i8> [[B]])
; ANYLE-NEXT: [[R:%.*]] = extractelement <8 x i8> [[B]], i64 3
; ANYLE-NEXT: ret i8 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_wide_source_uses(
; ANYBE-NEXT: [[I:%.*]] = insertelement <2 x i32> undef, i32 [[X:%.*]], i64 0
; ANYBE-NEXT: [[B:%.*]] = bitcast <2 x i32> [[I]] to <8 x i8>
; ANYBE-NEXT: call void @use(<8 x i8> [[B]])
; ANYBE-NEXT: [[R:%.*]] = trunc i32 [[X]] to i8
; ANYBE-NEXT: ret i8 [[R]]
;
%i = insertelement <2 x i32> undef, i32 %x, i32 0
%b = bitcast <2 x i32> %i to <8 x i8>
call void @use(<8 x i8> %b)
%r = extractelement <8 x i8> %b, i32 3
ret i8 %r
}
define float @bitcasted_inselt_to_FP(i64 %x) {
; ANYLE-LABEL: @bitcasted_inselt_to_FP(
; ANYLE-NEXT: [[TMP1:%.*]] = lshr i64 [[X:%.*]], 32
; ANYLE-NEXT: [[TMP2:%.*]] = trunc i64 [[TMP1]] to i32
; ANYLE-NEXT: [[R:%.*]] = bitcast i32 [[TMP2]] to float
; ANYLE-NEXT: ret float [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_to_FP(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
; ANYBE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float
; ANYBE-NEXT: ret float [[R]]
;
%i = insertelement <2 x i64> undef, i64 %x, i32 0
%b = bitcast <2 x i64> %i to <4 x float>
%r = extractelement <4 x float> %b, i32 1
ret float %r
}
declare void @use_v2i128(<2 x i128>)
declare void @use_v8f32(<8 x float>)
define float @bitcasted_inselt_to_FP_uses(i128 %x) {
; ANY-LABEL: @bitcasted_inselt_to_FP_uses(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x i128> undef, i128 [[X:%.*]], i64 0
; ANY-NEXT: call void @use_v2i128(<2 x i128> [[I]])
; ANY-NEXT: [[B:%.*]] = bitcast <2 x i128> [[I]] to <8 x float>
; ANY-NEXT: [[R:%.*]] = extractelement <8 x float> [[B]], i64 1
; ANY-NEXT: ret float [[R]]
;
%i = insertelement <2 x i128> undef, i128 %x, i32 0
call void @use_v2i128(<2 x i128> %i)
%b = bitcast <2 x i128> %i to <8 x float>
%r = extractelement <8 x float> %b, i32 1
ret float %r
}
define float @bitcasted_inselt_to_FP_uses2(i128 %x) {
; ANY-LABEL: @bitcasted_inselt_to_FP_uses2(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x i128> undef, i128 [[X:%.*]], i64 0
; ANY-NEXT: [[B:%.*]] = bitcast <2 x i128> [[I]] to <8 x float>
; ANY-NEXT: call void @use_v8f32(<8 x float> [[B]])
; ANY-NEXT: [[R:%.*]] = extractelement <8 x float> [[B]], i64 1
; ANY-NEXT: ret float [[R]]
;
%i = insertelement <2 x i128> undef, i128 %x, i32 0
%b = bitcast <2 x i128> %i to <8 x float>
call void @use_v8f32(<8 x float> %b)
%r = extractelement <8 x float> %b, i32 1
ret float %r
}
define i32 @bitcasted_inselt_from_FP(double %x) {
; ANYLE-LABEL: @bitcasted_inselt_from_FP(
; ANYLE-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
; ANYLE-NEXT: [[TMP2:%.*]] = lshr i64 [[TMP1]], 32
; ANYLE-NEXT: [[R:%.*]] = trunc i64 [[TMP2]] to i32
; ANYLE-NEXT: ret i32 [[R]]
;
; ANYBE-LABEL: @bitcasted_inselt_from_FP(
; ANYBE-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
; ANYBE-NEXT: [[R:%.*]] = trunc i64 [[TMP1]] to i32
; ANYBE-NEXT: ret i32 [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
%b = bitcast <2 x double> %i to <4 x i32>
%r = extractelement <4 x i32> %b, i32 1
ret i32 %r
}
declare void @use_v2f64(<2 x double>)
declare void @use_v8i16(<8 x i16>)
define i16 @bitcasted_inselt_from_FP_uses(double %x) {
; ANY-LABEL: @bitcasted_inselt_from_FP_uses(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i64 0
; ANY-NEXT: call void @use_v2f64(<2 x double> [[I]])
; ANY-NEXT: [[B:%.*]] = bitcast <2 x double> [[I]] to <8 x i16>
; ANY-NEXT: [[R:%.*]] = extractelement <8 x i16> [[B]], i64 1
; ANY-NEXT: ret i16 [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
call void @use_v2f64(<2 x double> %i)
%b = bitcast <2 x double> %i to <8 x i16>
%r = extractelement <8 x i16> %b, i32 1
ret i16 %r
}
define i16 @bitcasted_inselt_from_FP_uses2(double %x) {
; ANY-LABEL: @bitcasted_inselt_from_FP_uses2(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i64 0
; ANY-NEXT: [[B:%.*]] = bitcast <2 x double> [[I]] to <8 x i16>
; ANY-NEXT: call void @use_v8i16(<8 x i16> [[B]])
; ANY-NEXT: [[R:%.*]] = extractelement <8 x i16> [[B]], i64 1
; ANY-NEXT: ret i16 [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
%b = bitcast <2 x double> %i to <8 x i16>
call void @use_v8i16(<8 x i16> %b)
%r = extractelement <8 x i16> %b, i32 1
ret i16 %r
}
define float @bitcasted_inselt_to_and_from_FP(double %x) {
; ANY-LABEL: @bitcasted_inselt_to_and_from_FP(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i64 0
; ANY-NEXT: [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
; ANY-NEXT: [[R:%.*]] = extractelement <4 x float> [[B]], i64 1
; ANY-NEXT: ret float [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
%b = bitcast <2 x double> %i to <4 x float>
%r = extractelement <4 x float> %b, i32 1
ret float %r
}
define float @bitcasted_inselt_to_and_from_FP_uses(double %x) {
; ANY-LABEL: @bitcasted_inselt_to_and_from_FP_uses(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i64 0
; ANY-NEXT: call void @use_v2f64(<2 x double> [[I]])
; ANY-NEXT: [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
; ANY-NEXT: [[R:%.*]] = extractelement <4 x float> [[B]], i64 1
; ANY-NEXT: ret float [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
call void @use_v2f64(<2 x double> %i)
%b = bitcast <2 x double> %i to <4 x float>
%r = extractelement <4 x float> %b, i32 1
ret float %r
}
declare void @use_v4f32(<4 x float>)
define float @bitcasted_inselt_to_and_from_FP_uses2(double %x) {
; ANY-LABEL: @bitcasted_inselt_to_and_from_FP_uses2(
; ANY-NEXT: [[I:%.*]] = insertelement <2 x double> undef, double [[X:%.*]], i64 0
; ANY-NEXT: [[B:%.*]] = bitcast <2 x double> [[I]] to <4 x float>
; ANY-NEXT: call void @use_v4f32(<4 x float> [[B]])
; ANY-NEXT: [[R:%.*]] = extractelement <4 x float> [[B]], i64 1
; ANY-NEXT: ret float [[R]]
;
%i = insertelement <2 x double> undef, double %x, i32 0
%b = bitcast <2 x double> %i to <4 x float>
call void @use_v4f32(<4 x float> %b)
%r = extractelement <4 x float> %b, i32 1
ret float %r
}
; This would crash/assert because the logic for collectShuffleElements()
; does not consider the possibility of invalid insert/extract operands.
define <4 x double> @invalid_extractelement(<2 x double> %a, <4 x double> %b, ptr %p) {
; ANY-LABEL: @invalid_extractelement(
; ANY-NEXT: [[TMP1:%.*]] = shufflevector <2 x double> [[A:%.*]], <2 x double> poison, <4 x i32> <i32 0, i32 undef, i32 undef, i32 undef>
; ANY-NEXT: [[T4:%.*]] = shufflevector <4 x double> [[B:%.*]], <4 x double> [[TMP1]], <4 x i32> <i32 undef, i32 1, i32 4, i32 3>
; ANY-NEXT: [[E:%.*]] = extractelement <4 x double> [[B]], i64 1
; ANY-NEXT: store double [[E]], ptr [[P:%.*]], align 8
; ANY-NEXT: ret <4 x double> [[T4]]
;
%t3 = extractelement <2 x double> %a, i32 0
%t4 = insertelement <4 x double> %b, double %t3, i32 2
%e = extractelement <4 x double> %t4, i32 1
store double %e, ptr %p
%e1 = extractelement <2 x double> %a, i32 4 ; invalid index
%r = insertelement <4 x double> %t4, double %e1, i64 0
ret <4 x double> %r
}
; i32 is a desirable/supported type independent of data layout.
define i8 @bitcast_scalar_supported_type_index0(i32 %x) {
; ANYLE-LABEL: @bitcast_scalar_supported_type_index0(
; ANYLE-NEXT: [[R:%.*]] = trunc i32 [[X:%.*]] to i8
; ANYLE-NEXT: ret i8 [[R]]
;
; ANYBE-LABEL: @bitcast_scalar_supported_type_index0(
; ANYBE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 24
; ANYBE-NEXT: [[R:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i8
; ANYBE-NEXT: ret i8 [[R]]
;
%v = bitcast i32 %x to <4 x i8>
%r = extractelement <4 x i8> %v, i8 0
ret i8 %r
}
define i8 @bitcast_scalar_supported_type_index2(i32 %x) {
; ANYLE-LABEL: @bitcast_scalar_supported_type_index2(
; ANYLE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16
; ANYLE-NEXT: [[R:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i8
; ANYLE-NEXT: ret i8 [[R]]
;
; ANYBE-LABEL: @bitcast_scalar_supported_type_index2(
; ANYBE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 8
; ANYBE-NEXT: [[R:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i8
; ANYBE-NEXT: ret i8 [[R]]
;
%v = bitcast i32 %x to <4 x i8>
%r = extractelement <4 x i8> %v, i64 2
ret i8 %r
}
; i64 is legal based on data layout.
define i4 @bitcast_scalar_legal_type_index3(i64 %x) {
; LE64-LABEL: @bitcast_scalar_legal_type_index3(
; LE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 12
; LE64-NEXT: [[R:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i4
; LE64-NEXT: ret i4 [[R]]
;
; LE128-LABEL: @bitcast_scalar_legal_type_index3(
; LE128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <16 x i4>
; LE128-NEXT: [[R:%.*]] = extractelement <16 x i4> [[V]], i64 3
; LE128-NEXT: ret i4 [[R]]
;
; BE64-LABEL: @bitcast_scalar_legal_type_index3(
; BE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 48
; BE64-NEXT: [[R:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i4
; BE64-NEXT: ret i4 [[R]]
;
; BE128-LABEL: @bitcast_scalar_legal_type_index3(
; BE128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <16 x i4>
; BE128-NEXT: [[R:%.*]] = extractelement <16 x i4> [[V]], i64 3
; BE128-NEXT: ret i4 [[R]]
;
%v = bitcast i64 %x to <16 x i4>
%r = extractelement <16 x i4> %v, i64 3
ret i4 %r
}
; negative test - don't create a shift for an illegal type.
define i8 @bitcast_scalar_illegal_type_index1(i128 %x) {
; LE64-LABEL: @bitcast_scalar_illegal_type_index1(
; LE64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <16 x i8>
; LE64-NEXT: [[R:%.*]] = extractelement <16 x i8> [[V]], i64 1
; LE64-NEXT: ret i8 [[R]]
;
; LE128-LABEL: @bitcast_scalar_illegal_type_index1(
; LE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i128 [[X:%.*]], 8
; LE128-NEXT: [[R:%.*]] = trunc i128 [[EXTELT_OFFSET]] to i8
; LE128-NEXT: ret i8 [[R]]
;
; BE64-LABEL: @bitcast_scalar_illegal_type_index1(
; BE64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <16 x i8>
; BE64-NEXT: [[R:%.*]] = extractelement <16 x i8> [[V]], i64 1
; BE64-NEXT: ret i8 [[R]]
;
; BE128-LABEL: @bitcast_scalar_illegal_type_index1(
; BE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i128 [[X:%.*]], 112
; BE128-NEXT: [[R:%.*]] = trunc i128 [[EXTELT_OFFSET]] to i8
; BE128-NEXT: ret i8 [[R]]
;
%v = bitcast i128 %x to <16 x i8>
%r = extractelement <16 x i8> %v, i64 1
ret i8 %r
}
; negative test - can't use shift/trunc on FP
define i8 @bitcast_fp_index0(float %x) {
; ANY-LABEL: @bitcast_fp_index0(
; ANY-NEXT: [[V:%.*]] = bitcast float [[X:%.*]] to <4 x i8>
; ANY-NEXT: [[R:%.*]] = extractelement <4 x i8> [[V]], i64 0
; ANY-NEXT: ret i8 [[R]]
;
%v = bitcast float %x to <4 x i8>
%r = extractelement <4 x i8> %v, i8 0
ret i8 %r
}
define half @bitcast_fp16vec_index0(i32 %x) {
; ANYLE-LABEL: @bitcast_fp16vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
; ANYLE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half
; ANYLE-NEXT: ret half [[R]]
;
; ANYBE-LABEL: @bitcast_fp16vec_index0(
; ANYBE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16
; ANYBE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half
; ANYBE-NEXT: ret half [[R]]
;
%v = bitcast i32 %x to <2 x half>
%r = extractelement <2 x half> %v, i8 0
ret half %r
}
define half @bitcast_fp16vec_index1(i32 %x) {
; ANYLE-LABEL: @bitcast_fp16vec_index1(
; ANYLE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16
; ANYLE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half
; ANYLE-NEXT: ret half [[R]]
;
; ANYBE-LABEL: @bitcast_fp16vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
; ANYBE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half
; ANYBE-NEXT: ret half [[R]]
;
%v = bitcast i32 %x to <2 x half>
%r = extractelement <2 x half> %v, i8 1
ret half %r
}
define bfloat @bitcast_bfp16vec_index0(i32 %x) {
; ANYLE-LABEL: @bitcast_bfp16vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
; ANYLE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat
; ANYLE-NEXT: ret bfloat [[R]]
;
; ANYBE-LABEL: @bitcast_bfp16vec_index0(
; ANYBE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16
; ANYBE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat
; ANYBE-NEXT: ret bfloat [[R]]
;
%v = bitcast i32 %x to <2 x bfloat>
%r = extractelement <2 x bfloat> %v, i8 0
ret bfloat %r
}
define bfloat @bitcast_bfp16vec_index1(i32 %x) {
; ANYLE-LABEL: @bitcast_bfp16vec_index1(
; ANYLE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16
; ANYLE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat
; ANYLE-NEXT: ret bfloat [[R]]
;
; ANYBE-LABEL: @bitcast_bfp16vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16
; ANYBE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat
; ANYBE-NEXT: ret bfloat [[R]]
;
%v = bitcast i32 %x to <2 x bfloat>
%r = extractelement <2 x bfloat> %v, i8 1
ret bfloat %r
}
define float @bitcast_fp32vec_index0(i64 %x) {
; ANYLE-LABEL: @bitcast_fp32vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
; ANYLE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float
; ANYLE-NEXT: ret float [[R]]
;
; BE64-LABEL: @bitcast_fp32vec_index0(
; BE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 32
; BE64-NEXT: [[TMP1:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i32
; BE64-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float
; BE64-NEXT: ret float [[R]]
;
; BE128-LABEL: @bitcast_fp32vec_index0(
; BE128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float>
; BE128-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 0
; BE128-NEXT: ret float [[R]]
;
%v = bitcast i64 %x to <2 x float>
%r = extractelement <2 x float> %v, i8 0
ret float %r
}
define float @bitcast_fp32vec_index1(i64 %x) {
; LE64-LABEL: @bitcast_fp32vec_index1(
; LE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 32
; LE64-NEXT: [[TMP1:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i32
; LE64-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float
; LE64-NEXT: ret float [[R]]
;
; LE128-LABEL: @bitcast_fp32vec_index1(
; LE128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float>
; LE128-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 1
; LE128-NEXT: ret float [[R]]
;
; ANYBE-LABEL: @bitcast_fp32vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32
; ANYBE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float
; ANYBE-NEXT: ret float [[R]]
;
%v = bitcast i64 %x to <2 x float>
%r = extractelement <2 x float> %v, i8 1
ret float %r
}
define double @bitcast_fp64vec64_index0(i64 %x) {
; ANY-LABEL: @bitcast_fp64vec64_index0(
; ANY-NEXT: [[R:%.*]] = bitcast i64 [[X:%.*]] to double
; ANY-NEXT: ret double [[R]]
;
%v = bitcast i64 %x to <1 x double>
%r = extractelement <1 x double> %v, i8 0
ret double %r
}
define double @bitcast_fp64vec_index0(i128 %x) {
; ANYLE-LABEL: @bitcast_fp64vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64
; ANYLE-NEXT: [[R:%.*]] = bitcast i64 [[TMP1]] to double
; ANYLE-NEXT: ret double [[R]]
;
; BE64-LABEL: @bitcast_fp64vec_index0(
; BE64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double>
; BE64-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 0
; BE64-NEXT: ret double [[R]]
;
; BE128-LABEL: @bitcast_fp64vec_index0(
; BE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i128 [[X:%.*]], 64
; BE128-NEXT: [[TMP1:%.*]] = trunc i128 [[EXTELT_OFFSET]] to i64
; BE128-NEXT: [[R:%.*]] = bitcast i64 [[TMP1]] to double
; BE128-NEXT: ret double [[R]]
;
%v = bitcast i128 %x to <2 x double>
%r = extractelement <2 x double> %v, i8 0
ret double %r
}
define double @bitcast_fp64vec_index1(i128 %x) {
; LE64-LABEL: @bitcast_fp64vec_index1(
; LE64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double>
; LE64-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 1
; LE64-NEXT: ret double [[R]]
;
; LE128-LABEL: @bitcast_fp64vec_index1(
; LE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i128 [[X:%.*]], 64
; LE128-NEXT: [[TMP1:%.*]] = trunc i128 [[EXTELT_OFFSET]] to i64
; LE128-NEXT: [[R:%.*]] = bitcast i64 [[TMP1]] to double
; LE128-NEXT: ret double [[R]]
;
; ANYBE-LABEL: @bitcast_fp64vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64
; ANYBE-NEXT: [[R:%.*]] = bitcast i64 [[TMP1]] to double
; ANYBE-NEXT: ret double [[R]]
;
%v = bitcast i128 %x to <2 x double>
%r = extractelement <2 x double> %v, i8 1
ret double %r
}
; negative test - input integer should be legal
define x86_fp80 @bitcast_x86fp80vec_index0(i160 %x) {
; ANYLE-LABEL: @bitcast_x86fp80vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i160 [[X:%.*]] to i80
; ANYLE-NEXT: [[R:%.*]] = bitcast i80 [[TMP1]] to x86_fp80
; ANYLE-NEXT: ret x86_fp80 [[R]]
;
; ANYBE-LABEL: @bitcast_x86fp80vec_index0(
; ANYBE-NEXT: [[V:%.*]] = bitcast i160 [[X:%.*]] to <2 x x86_fp80>
; ANYBE-NEXT: [[R:%.*]] = extractelement <2 x x86_fp80> [[V]], i64 0
; ANYBE-NEXT: ret x86_fp80 [[R]]
;
%v = bitcast i160 %x to <2 x x86_fp80>
%r = extractelement <2 x x86_fp80> %v, i8 0
ret x86_fp80 %r
}
; negative test - input integer should be legal
define x86_fp80 @bitcast_x86fp80vec_index1(i160 %x) {
; ANYLE-LABEL: @bitcast_x86fp80vec_index1(
; ANYLE-NEXT: [[V:%.*]] = bitcast i160 [[X:%.*]] to <2 x x86_fp80>
; ANYLE-NEXT: [[R:%.*]] = extractelement <2 x x86_fp80> [[V]], i64 1
; ANYLE-NEXT: ret x86_fp80 [[R]]
;
; ANYBE-LABEL: @bitcast_x86fp80vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i160 [[X:%.*]] to i80
; ANYBE-NEXT: [[R:%.*]] = bitcast i80 [[TMP1]] to x86_fp80
; ANYBE-NEXT: ret x86_fp80 [[R]]
;
%v = bitcast i160 %x to <2 x x86_fp80>
%r = extractelement <2 x x86_fp80> %v, i8 1
ret x86_fp80 %r
}
; negative test - input integer should be legal
define fp128 @bitcast_fp128vec_index0(i256 %x) {
; ANYLE-LABEL: @bitcast_fp128vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i256 [[X:%.*]] to i128
; ANYLE-NEXT: [[R:%.*]] = bitcast i128 [[TMP1]] to fp128
; ANYLE-NEXT: ret fp128 [[R]]
;
; ANYBE-LABEL: @bitcast_fp128vec_index0(
; ANYBE-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x fp128>
; ANYBE-NEXT: [[R:%.*]] = extractelement <2 x fp128> [[V]], i64 0
; ANYBE-NEXT: ret fp128 [[R]]
;
%v = bitcast i256 %x to <2 x fp128>
%r = extractelement <2 x fp128> %v, i8 0
ret fp128 %r
}
; negative test - input integer should be legal
define fp128 @bitcast_fp128vec_index1(i256 %x) {
; ANYLE-LABEL: @bitcast_fp128vec_index1(
; ANYLE-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x fp128>
; ANYLE-NEXT: [[R:%.*]] = extractelement <2 x fp128> [[V]], i64 1
; ANYLE-NEXT: ret fp128 [[R]]
;
; ANYBE-LABEL: @bitcast_fp128vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i256 [[X:%.*]] to i128
; ANYBE-NEXT: [[R:%.*]] = bitcast i128 [[TMP1]] to fp128
; ANYBE-NEXT: ret fp128 [[R]]
;
%v = bitcast i256 %x to <2 x fp128>
%r = extractelement <2 x fp128> %v, i8 1
ret fp128 %r
}
; negative test - input integer should be legal
define ppc_fp128 @bitcast_ppcfp128vec_index0(i256 %x) {
; ANYLE-LABEL: @bitcast_ppcfp128vec_index0(
; ANYLE-NEXT: [[TMP1:%.*]] = trunc i256 [[X:%.*]] to i128
; ANYLE-NEXT: [[R:%.*]] = bitcast i128 [[TMP1]] to ppc_fp128
; ANYLE-NEXT: ret ppc_fp128 [[R]]
;
; ANYBE-LABEL: @bitcast_ppcfp128vec_index0(
; ANYBE-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x ppc_fp128>
; ANYBE-NEXT: [[R:%.*]] = extractelement <2 x ppc_fp128> [[V]], i64 0
; ANYBE-NEXT: ret ppc_fp128 [[R]]
;
%v = bitcast i256 %x to <2 x ppc_fp128>
%r = extractelement <2 x ppc_fp128> %v, i8 0
ret ppc_fp128 %r
}
; negative test -input integer should be legal
define ppc_fp128 @bitcast_ppcfp128vec_index1(i256 %x) {
; ANYLE-LABEL: @bitcast_ppcfp128vec_index1(
; ANYLE-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x ppc_fp128>
; ANYLE-NEXT: [[R:%.*]] = extractelement <2 x ppc_fp128> [[V]], i64 1
; ANYLE-NEXT: ret ppc_fp128 [[R]]
;
; ANYBE-LABEL: @bitcast_ppcfp128vec_index1(
; ANYBE-NEXT: [[TMP1:%.*]] = trunc i256 [[X:%.*]] to i128
; ANYBE-NEXT: [[R:%.*]] = bitcast i128 [[TMP1]] to ppc_fp128
; ANYBE-NEXT: ret ppc_fp128 [[R]]
;
%v = bitcast i256 %x to <2 x ppc_fp128>
%r = extractelement <2 x ppc_fp128> %v, i8 1
ret ppc_fp128 %r
}
; negative test - input integer should be legal
define i8 @bitcast_scalar_index_variable(i32 %x, i64 %y) {
; ANY-LABEL: @bitcast_scalar_index_variable(
; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <4 x i8>
; ANY-NEXT: [[R:%.*]] = extractelement <4 x i8> [[V]], i64 [[Y:%.*]]
; ANY-NEXT: ret i8 [[R]]
;
%v = bitcast i32 %x to <4 x i8>
%r = extractelement <4 x i8> %v, i64 %y
ret i8 %r
}
; extra use is ok if we don't need a shift
define i8 @bitcast_scalar_index0_use(i64 %x) {
; ANYLE-LABEL: @bitcast_scalar_index0_use(
; ANYLE-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <8 x i8>
; ANYLE-NEXT: call void @use(<8 x i8> [[V]])
; ANYLE-NEXT: [[R:%.*]] = trunc i64 [[X]] to i8
; ANYLE-NEXT: ret i8 [[R]]
;
; ANYBE-LABEL: @bitcast_scalar_index0_use(
; ANYBE-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <8 x i8>
; ANYBE-NEXT: call void @use(<8 x i8> [[V]])
; ANYBE-NEXT: [[R:%.*]] = extractelement <8 x i8> [[V]], i64 0
; ANYBE-NEXT: ret i8 [[R]]
;
%v = bitcast i64 %x to <8 x i8>
call void @use(<8 x i8> %v)
%r = extractelement <8 x i8> %v, i64 0
ret i8 %r
}
define i1 @bit_extract_cmp(i64 %x) {
; LE64-LABEL: @bit_extract_cmp(
; LE64-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 9223372032559808512
; LE64-NEXT: [[R:%.*]] = icmp eq i64 [[TMP1]], 0
; LE64-NEXT: ret i1 [[R]]
;
; LE128-LABEL: @bit_extract_cmp(
; LE128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float>
; LE128-NEXT: [[E:%.*]] = extractelement <2 x float> [[V]], i64 1
; LE128-NEXT: [[R:%.*]] = fcmp oeq float [[E]], 0.000000e+00
; LE128-NEXT: ret i1 [[R]]
;
; ANYBE-LABEL: @bit_extract_cmp(
; ANYBE-NEXT: [[TMP1:%.*]] = and i64 [[X:%.*]], 2147483647
; ANYBE-NEXT: [[R:%.*]] = icmp eq i64 [[TMP1]], 0
; ANYBE-NEXT: ret i1 [[R]]
;
%v = bitcast i64 %x to <2 x float>
%e = extractelement <2 x float> %v, i8 1
%r = fcmp oeq float %e, 0.0
ret i1 %r
}
define i32 @extelt_select_const_operand_vector(i1 %c) {
; ANY-LABEL: @extelt_select_const_operand_vector(
; ANY-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i32 4, i32 7
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%r = extractelement <3 x i32> %s, i32 2
ret i32 %r
}
define float @extelt_select_const_operand_vector_float(i1 %c) {
; ANY-LABEL: @extelt_select_const_operand_vector_float(
; ANY-NEXT: [[R:%.*]] = select i1 [[C:%.*]], float 4.000000e+00, float 7.000000e+00
; ANY-NEXT: ret float [[R]]
;
%s = select i1 %c, <3 x float> <float 2.0, float 3.0, float 4.0>, <3 x float> <float 5.0, float 6.0, float 7.0>
%r = extractelement <3 x float> %s, i32 2
ret float %r
}
define i32 @extelt_vecselect_const_operand_vector(<3 x i1> %c) {
; ANY-LABEL: @extelt_vecselect_const_operand_vector(
; ANY-NEXT: [[S:%.*]] = select <3 x i1> [[C:%.*]], <3 x i32> <i32 poison, i32 poison, i32 4>, <3 x i32> <i32 poison, i32 poison, i32 7>
; ANY-NEXT: [[R:%.*]] = extractelement <3 x i32> [[S]], i64 2
; ANY-NEXT: ret i32 [[R]]
;
%s = select <3 x i1> %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%r = extractelement <3 x i32> %s, i32 2
ret i32 %r
}
define i32 @extelt_select_const_operand_extractelt_use(i1 %c) {
; ANY-LABEL: @extelt_select_const_operand_extractelt_use(
; ANY-NEXT: [[E:%.*]] = select i1 [[C:%.*]], i32 4, i32 7
; ANY-NEXT: [[M:%.*]] = shl nuw nsw i32 [[E]], 1
; ANY-NEXT: [[M_2:%.*]] = shl nuw nsw i32 [[E]], 2
; ANY-NEXT: [[R:%.*]] = mul nuw nsw i32 [[M]], [[M_2]]
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%e = extractelement <3 x i32> %s, i32 2
%m = mul i32 %e, 2
%m.2 = mul i32 %e, 4
%r = mul i32 %m, %m.2
ret i32 %r
}
define i32 @extelt_select_const_operand_select_use(i1 %c) {
; ANY-LABEL: @extelt_select_const_operand_select_use(
; ANY-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <3 x i32> <i32 poison, i32 3, i32 4>, <3 x i32> <i32 poison, i32 6, i32 7>
; ANY-NEXT: [[E:%.*]] = extractelement <3 x i32> [[S]], i64 2
; ANY-NEXT: [[E_2:%.*]] = extractelement <3 x i32> [[S]], i64 1
; ANY-NEXT: [[R:%.*]] = mul i32 [[E]], [[E_2]]
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%e = extractelement <3 x i32> %s, i32 2
%e.2 = extractelement <3 x i32> %s, i32 1
%r = mul i32 %e, %e.2
ret i32 %r
}
define i32 @extelt_select_const_operand_vector_cond_index(i1 %c) {
; ANY-LABEL: @extelt_select_const_operand_vector_cond_index(
; ANY-NEXT: [[E:%.*]] = select i1 [[C:%.*]], i32 3, i32 4
; ANY-NEXT: [[S:%.*]] = select i1 [[C]], <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
; ANY-NEXT: [[R:%.*]] = extractelement <3 x i32> [[S]], i32 [[E]]
; ANY-NEXT: ret i32 [[R]]
;
%e = select i1 %c, i32 3, i32 4
%s = select i1 %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%r = extractelement <3 x i32> %s, i32 %e
ret i32 %r
}
define i32 @extelt_select_const_operand_vector_var_index(i1 %c, i32 %e) {
; ANY-LABEL: @extelt_select_const_operand_vector_var_index(
; ANY-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
; ANY-NEXT: [[R:%.*]] = extractelement <3 x i32> [[S]], i32 [[E:%.*]]
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 2, i32 3, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
%r = extractelement <3 x i32> %s, i32 %e
ret i32 %r
}
define i32 @extelt_select_var_const_operand_vector(i1 %c, <3 x i32> %v) {
; ANY-LABEL: @extelt_select_var_const_operand_vector(
; ANY-NEXT: [[TMP1:%.*]] = extractelement <3 x i32> [[V:%.*]], i64 1
; ANY-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i32 [[TMP1]], i32 6
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> %v, <3 x i32> <i32 5, i32 6, i32 7>
%r = extractelement <3 x i32> %s, i32 1
ret i32 %r
}
define i32 @extelt_select_const_var_operand_vector(i1 %c, <3 x i32> %v) {
; ANY-LABEL: @extelt_select_const_var_operand_vector(
; ANY-NEXT: [[TMP1:%.*]] = extractelement <3 x i32> [[V:%.*]], i64 0
; ANY-NEXT: [[R:%.*]] = select i1 [[C:%.*]], i32 5, i32 [[TMP1]]
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 5, i32 6, i32 7>, <3 x i32> %v
%r = extractelement <3 x i32> %s, i32 0
ret i32 %r
}
declare void @use_select(<3 x i32>)
define i32 @extelt_select_const_var_operands_vector_extra_use(i1 %c, <3 x i32> %x) {
; ANY-LABEL: @extelt_select_const_var_operands_vector_extra_use(
; ANY-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <3 x i32> <i32 42, i32 5, i32 4>, <3 x i32> [[X:%.*]]
; ANY-NEXT: call void @use_select(<3 x i32> [[S]])
; ANY-NEXT: [[R:%.*]] = extractelement <3 x i32> [[S]], i64 0
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 42, i32 5, i32 4>, <3 x i32> %x
call void @use_select(<3 x i32> %s)
%r = extractelement <3 x i32> %s, i64 0
ret i32 %r
}
define i32 @extelt_select_const_operands_vector_extra_use_2(i1 %c) {
; ANY-LABEL: @extelt_select_const_operands_vector_extra_use_2(
; ANY-NEXT: [[S:%.*]] = select i1 [[C:%.*]], <3 x i32> <i32 42, i32 5, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
; ANY-NEXT: call void @use_select(<3 x i32> [[S]])
; ANY-NEXT: [[R:%.*]] = extractelement <3 x i32> [[S]], i64 0
; ANY-NEXT: ret i32 [[R]]
;
%s = select i1 %c, <3 x i32> <i32 42, i32 5, i32 4>, <3 x i32> <i32 5, i32 6, i32 7>
call void @use_select(<3 x i32> %s)
%r = extractelement <3 x i32> %s, i64 0
ret i32 %r
}