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 @@ -1460,16 +1460,17 @@ // %d = ashr i32 %a, 30 Value *A = nullptr; // TODO: Eventually this could be subsumed by EvaluateInDifferentType. - ConstantInt *BA = nullptr, *CA = nullptr; - if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A)), m_ConstantInt(BA)), - m_ConstantInt(CA))) && + Constant *BA = nullptr, *CA = nullptr; + if (match(Src, m_AShr(m_Shl(m_Trunc(m_Value(A)), m_Constant(BA)), + m_Constant(CA))) && BA == CA && A->getType() == CI.getType()) { unsigned MidSize = Src->getType()->getScalarSizeInBits(); unsigned SrcDstSize = CI.getType()->getScalarSizeInBits(); - unsigned ShAmt = CA->getZExtValue()+SrcDstSize-MidSize; - Constant *ShAmtV = ConstantInt::get(CI.getType(), ShAmt); - A = Builder.CreateShl(A, ShAmtV, CI.getName()); - return BinaryOperator::CreateAShr(A, ShAmtV); + Constant *SizeDiff = ConstantInt::get(CA->getType(), SrcDstSize - MidSize); + Constant *ShAmt = ConstantExpr::getAdd(CA, SizeDiff); + Constant *ShAmtExt = ConstantExpr::getSExt(ShAmt, CI.getType()); + A = Builder.CreateShl(A, ShAmtExt, CI.getName()); + return BinaryOperator::CreateAShr(A, ShAmtExt); } return nullptr; diff --git a/llvm/test/Transforms/InstCombine/sext.ll b/llvm/test/Transforms/InstCombine/sext.ll --- a/llvm/test/Transforms/InstCombine/sext.ll +++ b/llvm/test/Transforms/InstCombine/sext.ll @@ -140,10 +140,8 @@ define <2 x i32> @test10_vec(<2 x i32> %i) { ; CHECK-LABEL: @test10_vec( -; CHECK-NEXT: [[A:%.*]] = trunc <2 x i32> [[I:%.*]] to <2 x i8> -; CHECK-NEXT: [[B:%.*]] = shl <2 x i8> [[A]], -; CHECK-NEXT: [[C:%.*]] = ashr exact <2 x i8> [[B]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i8> [[C]] to <2 x i32> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i32> [[I:%.*]], +; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i32> [[D1]], ; CHECK-NEXT: ret <2 x i32> [[D]] ; %A = trunc <2 x i32> %i to <2 x i8> @@ -155,10 +153,8 @@ define <2 x i32> @test10_vec_nonuniform(<2 x i32> %i) { ; CHECK-LABEL: @test10_vec_nonuniform( -; CHECK-NEXT: [[A:%.*]] = trunc <2 x i32> [[I:%.*]] to <2 x i8> -; CHECK-NEXT: [[B:%.*]] = shl <2 x i8> [[A]], -; CHECK-NEXT: [[C:%.*]] = ashr <2 x i8> [[B]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i8> [[C]] to <2 x i32> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i32> [[I:%.*]], +; CHECK-NEXT: [[D:%.*]] = ashr <2 x i32> [[D1]], ; CHECK-NEXT: ret <2 x i32> [[D]] ; %A = trunc <2 x i32> %i to <2 x i8> @@ -170,10 +166,8 @@ define <2 x i32> @test10_vec_undef(<2 x i32> %i) { ; CHECK-LABEL: @test10_vec_undef( -; CHECK-NEXT: [[A:%.*]] = trunc <2 x i32> [[I:%.*]] to <2 x i8> -; CHECK-NEXT: [[B:%.*]] = shl <2 x i8> [[A]], -; CHECK-NEXT: [[C:%.*]] = ashr <2 x i8> [[B]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i8> [[C]] to <2 x i32> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i32> [[I:%.*]], +; CHECK-NEXT: [[D:%.*]] = ashr <2 x i32> [[D1]], ; CHECK-NEXT: ret <2 x i32> [[D]] ; %A = trunc <2 x i32> %i to <2 x i8> 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 @@ -82,9 +82,8 @@ define <2 x i64> @test2_vec(<2 x i64> %a) { ; CHECK-LABEL: @test2_vec( ; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> -; CHECK-NEXT: [[C:%.*]] = shl <2 x i32> [[B]], -; CHECK-NEXT: [[Q:%.*]] = ashr exact <2 x i32> [[C]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i32> [[Q]] to <2 x i64> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], +; CHECK-NEXT: [[D:%.*]] = ashr exact <2 x i64> [[D1]], ; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) ; CHECK-NEXT: ret <2 x i64> [[D]] ; @@ -99,9 +98,8 @@ define <2 x i64> @test2_vec_nonuniform(<2 x i64> %a) { ; CHECK-LABEL: @test2_vec_nonuniform( ; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> -; CHECK-NEXT: [[C:%.*]] = shl <2 x i32> [[B]], -; CHECK-NEXT: [[Q:%.*]] = ashr <2 x i32> [[C]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i32> [[Q]] to <2 x i64> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], +; CHECK-NEXT: [[D:%.*]] = ashr <2 x i64> [[D1]], ; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) ; CHECK-NEXT: ret <2 x i64> [[D]] ; @@ -116,9 +114,8 @@ define <2 x i64> @test2_vec_undef(<2 x i64> %a) { ; CHECK-LABEL: @test2_vec_undef( ; CHECK-NEXT: [[B:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i32> -; CHECK-NEXT: [[C:%.*]] = shl <2 x i32> [[B]], -; CHECK-NEXT: [[Q:%.*]] = ashr <2 x i32> [[C]], -; CHECK-NEXT: [[D:%.*]] = sext <2 x i32> [[Q]] to <2 x i64> +; CHECK-NEXT: [[D1:%.*]] = shl <2 x i64> [[A]], +; CHECK-NEXT: [[D:%.*]] = ashr <2 x i64> [[D1]], ; CHECK-NEXT: call void @use_vec(<2 x i32> [[B]]) ; CHECK-NEXT: ret <2 x i64> [[D]] ;