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 @@ -407,19 +407,212 @@ ret i8 %r } -; negative test - can't have FP dest type without a cast - -define half @bitcast_fpvec_index0(i32 %x) { -; ANY-LABEL: @bitcast_fpvec_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]] +define half @bitcast_fp16vec_index0(i32 %x) { +; LE-LABEL: @bitcast_fp16vec_index0( +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE-NEXT: ret half [[R]] +; +; BE-LABEL: @bitcast_fp16vec_index0( +; BE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE-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) { +; LE-LABEL: @bitcast_fp16vec_index1( +; LE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; LE-NEXT: ret half [[R]] +; +; BE-LABEL: @bitcast_fp16vec_index1( +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to half +; BE-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) { +; LE-LABEL: @bitcast_bfp16vec_index0( +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE-NEXT: ret bfloat [[R]] +; +; BE-LABEL: @bitcast_bfp16vec_index0( +; BE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE-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) { +; LE-LABEL: @bitcast_bfp16vec_index1( +; LE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i32 [[X:%.*]], 16 +; LE-NEXT: [[TMP1:%.*]] = trunc i32 [[EXTELT_OFFSET]] to i16 +; LE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; LE-NEXT: ret bfloat [[R]] +; +; BE-LABEL: @bitcast_bfp16vec_index1( +; BE-NEXT: [[TMP1:%.*]] = trunc i32 [[X:%.*]] to i16 +; BE-NEXT: [[R:%.*]] = bitcast i16 [[TMP1]] to bfloat +; BE-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) { +; LE-LABEL: @bitcast_fp32vec_index0( +; LE-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 +; LE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; LE-NEXT: ret float [[R]] +; +; BE-LABEL: @bitcast_fp32vec_index0( +; BE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 32 +; BE-NEXT: [[TMP1:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i32 +; BE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; BE-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) { +; LE-LABEL: @bitcast_fp32vec_index1( +; LE-NEXT: [[EXTELT_OFFSET:%.*]] = lshr i64 [[X:%.*]], 32 +; LE-NEXT: [[TMP1:%.*]] = trunc i64 [[EXTELT_OFFSET]] to i32 +; LE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; LE-NEXT: ret float [[R]] +; +; BE-LABEL: @bitcast_fp32vec_index1( +; BE-NEXT: [[TMP1:%.*]] = trunc i64 [[X:%.*]] to i32 +; BE-NEXT: [[R:%.*]] = bitcast i32 [[TMP1]] to float +; BE-NEXT: ret float [[R]] +; + %v = bitcast i64 %x to <2 x float> + %r = extractelement <2 x float> %v, i8 1 + ret float %r +} + +; negative test - only support the width <= 32 + +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]] +; + %v = bitcast i128 %x to <2 x double> + %r = extractelement <2 x double> %v, i8 0 + ret double %r +} + +; negative test - only support the width <= 32 + +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]] +; + %v = bitcast i128 %x to <2 x double> + %r = extractelement <2 x double> %v, i8 1 + ret double %r +} + +; negative test - only support the width <= 32 + +define x86_fp80 @bitcast_x86fp80vec_index0(i160 %x) { +; ANY-LABEL: @bitcast_x86fp80vec_index0( +; ANY-NEXT: [[V:%.*]] = bitcast i160 [[X:%.*]] to <2 x x86_fp80> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x x86_fp80> [[V]], i64 0 +; ANY-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 - only support the width <= 32 + +define x86_fp80 @bitcast_x86fp80vec_index1(i160 %x) { +; ANY-LABEL: @bitcast_x86fp80vec_index1( +; ANY-NEXT: [[V:%.*]] = bitcast i160 [[X:%.*]] to <2 x x86_fp80> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x x86_fp80> [[V]], i64 1 +; ANY-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 - only support the width <= 32 + +define fp128 @bitcast_fp128vec_index0(i256 %x) { +; ANY-LABEL: @bitcast_fp128vec_index0( +; ANY-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x fp128> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x fp128> [[V]], i64 0 +; ANY-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 - only support the width <= 32 + +define fp128 @bitcast_fp128vec_index1(i256 %x) { +; ANY-LABEL: @bitcast_fp128vec_index1( +; ANY-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x fp128> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x fp128> [[V]], i64 1 +; ANY-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 - only support the width <= 32 + +define ppc_fp128 @bitcast_ppcfp128vec_index0(i256 %x) { +; ANY-LABEL: @bitcast_ppcfp128vec_index0( +; ANY-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x ppc_fp128> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x ppc_fp128> [[V]], i64 0 +; ANY-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 - only support the width <= 32 + +define ppc_fp128 @bitcast_ppcfp128vec_index1(i256 %x) { +; ANY-LABEL: @bitcast_ppcfp128vec_index1( +; ANY-NEXT: [[V:%.*]] = bitcast i256 [[X:%.*]] to <2 x ppc_fp128> +; ANY-NEXT: [[R:%.*]] = extractelement <2 x ppc_fp128> [[V]], i64 1 +; ANY-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 - need constant index define i8 @bitcast_scalar_index_variable(i32 %x, i64 %y) {