diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -714,7 +714,6 @@ Type *DestTy = Trunc.getType(), *SrcTy = Src->getType(); unsigned DestWidth = DestTy->getScalarSizeInBits(); unsigned SrcWidth = SrcTy->getScalarSizeInBits(); - ConstantInt *Cst; // Attempt to truncate the entire input expression tree to the destination // type. Only do this if the dest type is a simple type, don't convert the @@ -866,20 +865,19 @@ if (Instruction *I = shrinkInsertElt(Trunc, Builder)) return I; - if (Src->hasOneUse() && isa(SrcTy) && - shouldChangeType(SrcTy, DestTy)) { + if (Src->hasOneUse() && + (isa(SrcTy) || shouldChangeType(SrcTy, DestTy))) { // Transform "trunc (shl X, cst)" -> "shl (trunc X), cst" so long as the // dest type is native and cst < dest size. - if (match(Src, m_Shl(m_Value(A), m_ConstantInt(Cst))) && + if (match(Src, m_Shl(m_Value(A), m_Constant(C))) && !match(A, m_Shr(m_Value(), m_Constant()))) { // Skip shifts of shift by constants. It undoes a combine in // FoldShiftByConstant and is the extend in reg pattern. - if (Cst->getValue().ult(DestWidth)) { + APInt Threshold = APInt(C->getType()->getScalarSizeInBits(), DestWidth); + if (match(C, m_SpecificInt_ICMP(ICmpInst::ICMP_ULT, Threshold))) { Value *NewTrunc = Builder.CreateTrunc(A, DestTy, A->getName() + ".tr"); - - return BinaryOperator::Create( - Instruction::Shl, NewTrunc, - ConstantInt::get(DestTy, Cst->getValue().trunc(DestWidth))); + return BinaryOperator::Create(Instruction::Shl, NewTrunc, + ConstantExpr::getTrunc(C, DestTy)); } } } @@ -896,6 +894,7 @@ // ---> // extractelement <8 x i32> (bitcast <4 x i64> %X to <8 x i32>), i32 0 Value *VecOp; + ConstantInt *Cst; if (match(Src, m_OneUse(m_ExtractElt(m_Value(VecOp), m_ConstantInt(Cst))))) { auto *VecOpTy = cast(VecOp->getType()); unsigned VecNumElts = VecOpTy->getNumElements(); diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest-with-truncation-shl.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest-with-truncation-shl.ll --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest-with-truncation-shl.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest-with-truncation-shl.ll @@ -362,12 +362,11 @@ define <2 x i1> @t11_constants_vec_splat(<2 x i32> %x, <2 x i64> %y) { ; CHECK-LABEL: @t11_constants_vec_splat( -; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = shl <2 x i64> [[Y:%.*]], -; CHECK-NEXT: [[T1_TRUNC:%.*]] = trunc <2 x i64> [[T1]] to <2 x i32> -; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T0]], [[T1_TRUNC]] -; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[T3]] +; CHECK-NEXT: [[Y_TR:%.*]] = trunc <2 x i64> [[Y:%.*]] to <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y_TR]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[TMP3]] ; %t0 = lshr <2 x i32> %x, %t1 = shl <2 x i64> %y, @@ -378,12 +377,11 @@ } define <2 x i1> @t12_constants_vec_nonsplat(<2 x i32> %x, <2 x i64> %y) { ; CHECK-LABEL: @t12_constants_vec_nonsplat( -; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T1:%.*]] = shl <2 x i64> [[Y:%.*]], -; CHECK-NEXT: [[T1_TRUNC:%.*]] = trunc <2 x i64> [[T1]] to <2 x i32> -; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T0]], [[T1_TRUNC]] -; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer -; CHECK-NEXT: ret <2 x i1> [[T3]] +; CHECK-NEXT: [[Y_TR:%.*]] = trunc <2 x i64> [[Y:%.*]] to <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y_TR]] +; CHECK-NEXT: [[TMP3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer +; CHECK-NEXT: ret <2 x i1> [[TMP3]] ; %t0 = lshr <2 x i32> %x, %t1 = shl <2 x i64> %y, diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-with-truncation-shl.ll @@ -27,8 +27,8 @@ define <2 x i16> @t1_vec_splat(<2 x i32> %x, <2 x i16> %y) { ; CHECK-LABEL: @t1_vec_splat( -; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[T5:%.*]] = trunc <2 x i32> [[TMP1]] to <2 x i16> +; CHECK-NEXT: [[X_TR:%.*]] = trunc <2 x i32> [[X:%.*]] to <2 x i16> +; CHECK-NEXT: [[T5:%.*]] = shl <2 x i16> [[X_TR]], ; CHECK-NEXT: ret <2 x i16> [[T5]] ; %t0 = sub <2 x i16> , %y @@ -59,8 +59,8 @@ define <3 x i16> @t3_vec_nonsplat_undef0(<3 x i32> %x, <3 x i16> %y) { ; CHECK-LABEL: @t3_vec_nonsplat_undef0( -; CHECK-NEXT: [[TMP1:%.*]] = shl <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T5:%.*]] = trunc <3 x i32> [[TMP1]] to <3 x i16> +; CHECK-NEXT: [[X_TR:%.*]] = trunc <3 x i32> [[X:%.*]] to <3 x i16> +; CHECK-NEXT: [[T5:%.*]] = shl <3 x i16> [[X_TR]], ; CHECK-NEXT: ret <3 x i16> [[T5]] ; %t0 = sub <3 x i16> , %y @@ -74,8 +74,8 @@ define <3 x i16> @t4_vec_nonsplat_undef1(<3 x i32> %x, <3 x i16> %y) { ; CHECK-LABEL: @t4_vec_nonsplat_undef1( -; CHECK-NEXT: [[TMP1:%.*]] = shl <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T5:%.*]] = trunc <3 x i32> [[TMP1]] to <3 x i16> +; CHECK-NEXT: [[X_TR:%.*]] = trunc <3 x i32> [[X:%.*]] to <3 x i16> +; CHECK-NEXT: [[T5:%.*]] = shl <3 x i16> [[X_TR]], ; CHECK-NEXT: ret <3 x i16> [[T5]] ; %t0 = sub <3 x i16> , %y @@ -89,8 +89,8 @@ define <3 x i16> @t5_vec_nonsplat_undef1(<3 x i32> %x, <3 x i16> %y) { ; CHECK-LABEL: @t5_vec_nonsplat_undef1( -; CHECK-NEXT: [[TMP1:%.*]] = shl <3 x i32> [[X:%.*]], -; CHECK-NEXT: [[T5:%.*]] = trunc <3 x i32> [[TMP1]] to <3 x i16> +; CHECK-NEXT: [[X_TR:%.*]] = trunc <3 x i32> [[X:%.*]] to <3 x i16> +; CHECK-NEXT: [[T5:%.*]] = shl <3 x i16> [[X_TR]], ; CHECK-NEXT: ret <3 x i16> [[T5]] ; %t0 = sub <3 x i16> , %y diff --git a/llvm/test/Transforms/InstCombine/trunc.ll b/llvm/test/Transforms/InstCombine/trunc.ll --- a/llvm/test/Transforms/InstCombine/trunc.ll +++ b/llvm/test/Transforms/InstCombine/trunc.ll @@ -704,11 +704,11 @@ ret i32 %trunc } -; TODO: Should be able to handle vectors +; Should be able to handle vectors define <2 x i32> @trunc_shl_16_v2i32_v2i64(<2 x i64> %val) { ; CHECK-LABEL: @trunc_shl_16_v2i32_v2i64( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> +; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> +; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], ; CHECK-NEXT: ret <2 x i32> [[TRUNC]] ; %shl = shl <2 x i64> %val, @@ -718,8 +718,8 @@ define <2 x i32> @trunc_shl_nosplat_v2i32_v2i64(<2 x i64> %val) { ; CHECK-LABEL: @trunc_shl_nosplat_v2i32_v2i64( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> +; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> +; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], ; CHECK-NEXT: ret <2 x i32> [[TRUNC]] ; %shl = shl <2 x i64> %val, @@ -757,8 +757,8 @@ define <2 x i32> @trunc_shl_v2i32_v2i64_uniform(<2 x i64> %val) { ; CHECK-LABEL: @trunc_shl_v2i32_v2i64_uniform( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> +; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> +; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], ; CHECK-NEXT: ret <2 x i32> [[TRUNC]] ; %shl = shl <2 x i64> %val, @@ -768,8 +768,8 @@ define <2 x i32> @trunc_shl_v2i32_v2i64_undef(<2 x i64> %val) { ; CHECK-LABEL: @trunc_shl_v2i32_v2i64_undef( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> +; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> +; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], ; CHECK-NEXT: ret <2 x i32> [[TRUNC]] ; %shl = shl <2 x i64> %val, @@ -779,8 +779,8 @@ define <2 x i32> @trunc_shl_v2i32_v2i64_nonuniform(<2 x i64> %val) { ; CHECK-LABEL: @trunc_shl_v2i32_v2i64_nonuniform( -; CHECK-NEXT: [[SHL:%.*]] = shl <2 x i64> [[VAL:%.*]], -; CHECK-NEXT: [[TRUNC:%.*]] = trunc <2 x i64> [[SHL]] to <2 x i32> +; CHECK-NEXT: [[VAL_TR:%.*]] = trunc <2 x i64> [[VAL:%.*]] to <2 x i32> +; CHECK-NEXT: [[TRUNC:%.*]] = shl <2 x i32> [[VAL_TR]], ; CHECK-NEXT: ret <2 x i32> [[TRUNC]] ; %shl = shl <2 x i64> %val, @@ -865,8 +865,8 @@ define <8 x i16> @trunc_shl_v8i15_v8i32_15(<8 x i32> %a) { ; CHECK-LABEL: @trunc_shl_v8i15_v8i32_15( -; CHECK-NEXT: [[SHL:%.*]] = shl <8 x i32> [[A:%.*]], -; CHECK-NEXT: [[CONV:%.*]] = trunc <8 x i32> [[SHL]] to <8 x i16> +; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], ; CHECK-NEXT: ret <8 x i16> [[CONV]] ; %shl = shl <8 x i32> %a, @@ -894,8 +894,8 @@ define <8 x i16> @trunc_shl_v8i16_v8i32_4(<8 x i32> %a) { ; CHECK-LABEL: @trunc_shl_v8i16_v8i32_4( -; CHECK-NEXT: [[SHL:%.*]] = shl <8 x i32> [[A:%.*]], -; CHECK-NEXT: [[CONV:%.*]] = trunc <8 x i32> [[SHL]] to <8 x i16> +; CHECK-NEXT: [[A_TR:%.*]] = trunc <8 x i32> [[A:%.*]] to <8 x i16> +; CHECK-NEXT: [[CONV:%.*]] = shl <8 x i16> [[A_TR]], ; CHECK-NEXT: ret <8 x i16> [[CONV]] ; %shl = shl <8 x i32> %a,