diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp @@ -191,8 +191,7 @@ // If we are casting an integer to vector and extracting a portion, that is // a shift-right and truncate. - // TODO: Allow FP dest type by casting the trunc to FP? - if (X->getType()->isIntegerTy() && DestTy->isIntegerTy() && + if (X->getType()->isIntegerTy() && isDesirableIntType(X->getType()->getPrimitiveSizeInBits())) { assert(isa(Ext.getVectorOperand()->getType()) && "Expected fixed vector type for bitcast from scalar integer"); @@ -205,6 +204,12 @@ unsigned ShiftAmountC = ExtIndexC * DestTy->getPrimitiveSizeInBits(); if (!ShiftAmountC || Ext.getVectorOperand()->hasOneUse()) { Value *Lshr = Builder.CreateLShr(X, ShiftAmountC, "extelt.offset"); + if (DestTy->isFloatingPointTy()) { + Type *DstIntTy = IntegerType::getIntNTy( + Lshr->getContext(), DestTy->getPrimitiveSizeInBits()); + Value *Trunc = Builder.CreateTrunc(Lshr, DstIntTy); + return new BitCastInst(Trunc, DestTy); + } return new TruncInst(Lshr, DestTy); } } diff --git a/llvm/test/Transforms/InstCombine/extractelement.ll b/llvm/test/Transforms/InstCombine/extractelement.ll --- a/llvm/test/Transforms/InstCombine/extractelement.ll +++ b/llvm/test/Transforms/InstCombine/extractelement.ll @@ -527,10 +527,27 @@ } define half @bitcast_fp16vec_index0(i32 %x) { -; ANY-LABEL: @bitcast_fp16vec_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x half> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x half> [[V]], i64 0 -; ANY-NEXT: ret half [[R]] +; LE64-LABEL: @bitcast_fp16vec_index0( +; LE64-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE64-NEXT: ret half [[R]] +; +; BE64-LABEL: @bitcast_fp16vec_index0( +; BE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE64-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE64-NEXT: ret half [[R]] +; +; LE128-LABEL: @bitcast_fp16vec_index0( +; LE128-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE128-NEXT: ret half [[R]] +; +; BE128-LABEL: @bitcast_fp16vec_index0( +; BE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE128-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE128-NEXT: ret half [[R]] ; %v = bitcast i32 %x to <2 x half> %r = extractelement <2 x half> %v, i8 0 @@ -538,10 +555,27 @@ } define half @bitcast_fp16vec_index1(i32 %x) { -; ANY-LABEL: @bitcast_fp16vec_index1( -; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x half> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x half> [[V]], i64 1 -; ANY-NEXT: ret half [[R]] +; LE64-LABEL: @bitcast_fp16vec_index1( +; LE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE64-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE64-NEXT: ret half [[R]] +; +; BE64-LABEL: @bitcast_fp16vec_index1( +; BE64-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE64-NEXT: ret half [[R]] +; +; LE128-LABEL: @bitcast_fp16vec_index1( +; LE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE128-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE128-NEXT: ret half [[R]] +; +; BE128-LABEL: @bitcast_fp16vec_index1( +; BE128-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE128-NEXT: ret half [[R]] ; %v = bitcast i32 %x to <2 x half> %r = extractelement <2 x half> %v, i8 1 @@ -549,10 +583,27 @@ } define bfloat @bitcast_bfp16vec_index0(i32 %x) { -; ANY-LABEL: @bitcast_bfp16vec_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x bfloat> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x bfloat> [[V]], i64 0 -; ANY-NEXT: ret bfloat [[R]] +; LE64-LABEL: @bitcast_bfp16vec_index0( +; LE64-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE64-NEXT: ret bfloat [[R]] +; +; BE64-LABEL: @bitcast_bfp16vec_index0( +; BE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE64-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE64-NEXT: ret bfloat [[R]] +; +; LE128-LABEL: @bitcast_bfp16vec_index0( +; LE128-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE128-NEXT: ret bfloat [[R]] +; +; BE128-LABEL: @bitcast_bfp16vec_index0( +; BE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE128-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE128-NEXT: ret bfloat [[R]] ; %v = bitcast i32 %x to <2 x bfloat> %r = extractelement <2 x bfloat> %v, i8 0 @@ -560,10 +611,27 @@ } define bfloat @bitcast_bfp16vec_index1(i32 %x) { -; ANY-LABEL: @bitcast_bfp16vec_index1( -; ANY-NEXT: [[V:%.*]] = bitcast i32 [[X:%.*]] to <2 x bfloat> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x bfloat> [[V]], i64 1 -; ANY-NEXT: ret bfloat [[R]] +; LE64-LABEL: @bitcast_bfp16vec_index1( +; LE64-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE64-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE64-NEXT: ret bfloat [[R]] +; +; BE64-LABEL: @bitcast_bfp16vec_index1( +; BE64-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE64-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE64-NEXT: ret bfloat [[R]] +; +; LE128-LABEL: @bitcast_bfp16vec_index1( +; LE128-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE128-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE128-NEXT: ret bfloat [[R]] +; +; BE128-LABEL: @bitcast_bfp16vec_index1( +; BE128-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE128-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE128-NEXT: ret bfloat [[R]] ; %v = bitcast i32 %x to <2 x bfloat> %r = extractelement <2 x bfloat> %v, i8 1 @@ -571,10 +639,21 @@ } define float @bitcast_fp32vec_index0(i64 %x) { -; ANY-LABEL: @bitcast_fp32vec_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 0 -; ANY-NEXT: ret float [[R]] +; LE64-LABEL: @bitcast_fp32vec_index0( +; LE64-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 +; LE64-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; LE64-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]] +; +; ANY128-LABEL: @bitcast_fp32vec_index0( +; ANY128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float> +; ANY128-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 0 +; ANY128-NEXT: ret float [[R]] ; %v = bitcast i64 %x to <2 x float> %r = extractelement <2 x float> %v, i8 0 @@ -582,10 +661,21 @@ } define float @bitcast_fp32vec_index1(i64 %x) { -; ANY-LABEL: @bitcast_fp32vec_index1( -; ANY-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 1 -; ANY-NEXT: ret float [[R]] +; 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]] +; +; BE64-LABEL: @bitcast_fp32vec_index1( +; BE64-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 +; BE64-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; BE64-NEXT: ret float [[R]] +; +; ANY128-LABEL: @bitcast_fp32vec_index1( +; ANY128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <2 x float> +; ANY128-NEXT: [[R:%.*]] = extractelement <2 x float> [[V]], i64 1 +; ANY128-NEXT: ret float [[R]] ; %v = bitcast i64 %x to <2 x float> %r = extractelement <2 x float> %v, i8 1 @@ -593,10 +683,14 @@ } define double @bitcast_fp64vec64_index0(i64 %x) { -; ANY-LABEL: @bitcast_fp64vec64_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <1 x double> -; ANY-NEXT: [[R:%.*]] = extractelement <1 x double> [[V]], i64 0 -; ANY-NEXT: ret double [[R]] +; ANY64-LABEL: @bitcast_fp64vec64_index0( +; ANY64-NEXT: [[R:%.*]] = bitcast i64 [[X:%.*]] to double +; ANY64-NEXT: ret double [[R]] +; +; ANY128-LABEL: @bitcast_fp64vec64_index0( +; ANY128-NEXT: [[V:%.*]] = bitcast i64 [[X:%.*]] to <1 x double> +; ANY128-NEXT: [[R:%.*]] = extractelement <1 x double> [[V]], i64 0 +; ANY128-NEXT: ret double [[R]] ; %v = bitcast i64 %x to <1 x double> %r = extractelement <1 x double> %v, i8 0 @@ -604,10 +698,21 @@ } define double @bitcast_fp64vec_index0(i128 %x) { -; ANY-LABEL: @bitcast_fp64vec_index0( -; ANY-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 0 -; ANY-NEXT: ret double [[R]] +; ANY64-LABEL: @bitcast_fp64vec_index0( +; ANY64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double> +; ANY64-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 0 +; ANY64-NEXT: ret double [[R]] +; +; LE128-LABEL: @bitcast_fp64vec_index0( +; LE128-NEXT: [[TMP1:%.*]] = trunc i128 [[X:%.*]] to i64 +; LE128-NEXT: [[R:%.*]] = bitcast i64 [[TMP1]] to double +; LE128-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 @@ -615,10 +720,21 @@ } define double @bitcast_fp64vec_index1(i128 %x) { -; ANY-LABEL: @bitcast_fp64vec_index1( -; ANY-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double> -; ANY-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 1 -; ANY-NEXT: ret double [[R]] +; ANY64-LABEL: @bitcast_fp64vec_index1( +; ANY64-NEXT: [[V:%.*]] = bitcast i128 [[X:%.*]] to <2 x double> +; ANY64-NEXT: [[R:%.*]] = extractelement <2 x double> [[V]], i64 1 +; ANY64-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]] +; +; BE128-LABEL: @bitcast_fp64vec_index1( +; BE128-NEXT: [[TMP1:%.*]] = trunc i128 [[X:%.*]] 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 1