mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 04:02:41 +01:00
[InstCombine][x86] Constant fold psll intrinsics.
This excludes avx512 as I don't have hardware to verify. It excludes _dq variants because they are represented in the IR as <{2,4} x i64> when it's actually a byte shift of the entire i{128,265}. This also excludes _dq_bs as they aren't at all supported by the backend. There are also no corresponding instructions in the ISA. I have no idea why they exist... llvm-svn: 207058
This commit is contained in:
parent
00d0daca29
commit
65065bf94f
@ -556,6 +556,47 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Constant fold <A x Bi> << Ci.
|
||||
// FIXME: We don't handle _dq because it's a shift of an i128, but is
|
||||
// represented in the IR as <2 x i64>. A per element shift is wrong.
|
||||
case Intrinsic::x86_sse2_psll_d:
|
||||
case Intrinsic::x86_sse2_psll_q:
|
||||
case Intrinsic::x86_sse2_psll_w:
|
||||
case Intrinsic::x86_sse2_pslli_d:
|
||||
case Intrinsic::x86_sse2_pslli_q:
|
||||
case Intrinsic::x86_sse2_pslli_w:
|
||||
case Intrinsic::x86_avx2_psll_d:
|
||||
case Intrinsic::x86_avx2_psll_q:
|
||||
case Intrinsic::x86_avx2_psll_w:
|
||||
case Intrinsic::x86_avx2_pslli_d:
|
||||
case Intrinsic::x86_avx2_pslli_q:
|
||||
case Intrinsic::x86_avx2_pslli_w: {
|
||||
// Simplify if count is constant. To 0 if > BitWidth, otherwise to shl.
|
||||
auto CDV = dyn_cast<ConstantDataVector>(II->getArgOperand(1));
|
||||
auto CInt = dyn_cast<ConstantInt>(II->getArgOperand(1));
|
||||
if (!CDV && !CInt)
|
||||
break;
|
||||
ConstantInt *Count;
|
||||
if (CDV)
|
||||
Count = cast<ConstantInt>(CDV->getElementAsConstant(0));
|
||||
else
|
||||
Count = CInt;
|
||||
|
||||
auto Vec = II->getArgOperand(0);
|
||||
auto VT = cast<VectorType>(Vec->getType());
|
||||
if (Count->getZExtValue() >
|
||||
VT->getElementType()->getPrimitiveSizeInBits() - 1)
|
||||
return ReplaceInstUsesWith(
|
||||
CI, ConstantAggregateZero::get(Vec->getType()));
|
||||
else {
|
||||
unsigned VWidth = VT->getNumElements();
|
||||
// Get a constant vector of the same type as the first operand.
|
||||
auto VTCI = ConstantInt::get(VT->getElementType(), Count->getZExtValue());
|
||||
return BinaryOperator::CreateShl(
|
||||
Vec, Builder->CreateVectorSplat(VWidth, VTCI));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Intrinsic::x86_sse41_pmovsxbw:
|
||||
case Intrinsic::x86_sse41_pmovsxwd:
|
||||
|
@ -1,4 +1,5 @@
|
||||
; RUN: opt < %s -instcombine -S | FileCheck %s
|
||||
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
define i16 @test1(float %f) {
|
||||
entry:
|
||||
@ -337,3 +338,112 @@ define <4 x double> @test_vpermilvar_pd_256(<4 x double> %v) {
|
||||
%a = tail call <4 x double> @llvm.x86.avx.vpermilvar.pd.256(<4 x double> %v, <4 x i32> <i32 3, i32 2, i32 1, i32 0>)
|
||||
ret <4 x double> %a
|
||||
}
|
||||
|
||||
define <2 x i64> @test_sse2_1() nounwind readnone uwtable {
|
||||
%S = bitcast i32 1 to i32
|
||||
%1 = zext i32 %S to i64
|
||||
%2 = insertelement <2 x i64> undef, i64 %1, i32 0
|
||||
%3 = insertelement <2 x i64> %2, i64 0, i32 1
|
||||
%4 = bitcast <2 x i64> %3 to <8 x i16>
|
||||
%5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4)
|
||||
%6 = bitcast <8 x i16> %5 to <4 x i32>
|
||||
%7 = bitcast <2 x i64> %3 to <4 x i32>
|
||||
%8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7)
|
||||
%9 = bitcast <4 x i32> %8 to <2 x i64>
|
||||
%10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3)
|
||||
%11 = bitcast <2 x i64> %10 to <8 x i16>
|
||||
%12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S)
|
||||
%13 = bitcast <8 x i16> %12 to <4 x i32>
|
||||
%14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S)
|
||||
%15 = bitcast <4 x i32> %14 to <2 x i64>
|
||||
%16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S)
|
||||
ret <2 x i64> %16
|
||||
|
||||
; CHECK: test_sse2_1
|
||||
; CHECK: ret <2 x i64> <i64 72058418680037440, i64 144117112246370624>
|
||||
}
|
||||
|
||||
define <4 x i64> @test_avx2_1() nounwind readnone uwtable {
|
||||
%S = bitcast i32 1 to i32
|
||||
%1 = zext i32 %S to i64
|
||||
%2 = insertelement <2 x i64> undef, i64 %1, i32 0
|
||||
%3 = insertelement <2 x i64> %2, i64 0, i32 1
|
||||
%4 = bitcast <2 x i64> %3 to <8 x i16>
|
||||
%5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4)
|
||||
%6 = bitcast <16 x i16> %5 to <8 x i32>
|
||||
%7 = bitcast <2 x i64> %3 to <4 x i32>
|
||||
%8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7)
|
||||
%9 = bitcast <8 x i32> %8 to <4 x i64>
|
||||
%10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3)
|
||||
%11 = bitcast <4 x i64> %10 to <16 x i16>
|
||||
%12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S)
|
||||
%13 = bitcast <16 x i16> %12 to <8 x i32>
|
||||
%14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S)
|
||||
%15 = bitcast <8 x i32> %14 to <4 x i64>
|
||||
%16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S)
|
||||
ret <4 x i64> %16
|
||||
; CHECK: test_avx2_1
|
||||
; CHECK: ret <4 x i64> <i64 64, i64 128, i64 192, i64 256>
|
||||
}
|
||||
|
||||
define <2 x i64> @test_sse2_0() nounwind readnone uwtable {
|
||||
%S = bitcast i32 128 to i32
|
||||
%1 = zext i32 %S to i64
|
||||
%2 = insertelement <2 x i64> undef, i64 %1, i32 0
|
||||
%3 = insertelement <2 x i64> %2, i64 0, i32 1
|
||||
%4 = bitcast <2 x i64> %3 to <8 x i16>
|
||||
%5 = tail call <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16> <i16 1, i16 2, i16 3, i16 4, i16 5, i16 6, i16 7, i16 8>, <8 x i16> %4)
|
||||
%6 = bitcast <8 x i16> %5 to <4 x i32>
|
||||
%7 = bitcast <2 x i64> %3 to <4 x i32>
|
||||
%8 = tail call <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32> %6, <4 x i32> %7)
|
||||
%9 = bitcast <4 x i32> %8 to <2 x i64>
|
||||
%10 = tail call <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64> %9, <2 x i64> %3)
|
||||
%11 = bitcast <2 x i64> %10 to <8 x i16>
|
||||
%12 = tail call <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16> %11, i32 %S)
|
||||
%13 = bitcast <8 x i16> %12 to <4 x i32>
|
||||
%14 = tail call <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32> %13, i32 %S)
|
||||
%15 = bitcast <4 x i32> %14 to <2 x i64>
|
||||
%16 = tail call <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64> %15, i32 %S)
|
||||
ret <2 x i64> %16
|
||||
|
||||
; CHECK: test_sse2_0
|
||||
; CHECK: ret <2 x i64> zeroinitializer
|
||||
}
|
||||
|
||||
define <4 x i64> @test_avx2_0() nounwind readnone uwtable {
|
||||
%S = bitcast i32 128 to i32
|
||||
%1 = zext i32 %S to i64
|
||||
%2 = insertelement <2 x i64> undef, i64 %1, i32 0
|
||||
%3 = insertelement <2 x i64> %2, i64 0, i32 1
|
||||
%4 = bitcast <2 x i64> %3 to <8 x i16>
|
||||
%5 = tail call <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16> <i16 1, i16 0, i16 0, i16 0, i16 2, i16 0, i16 0, i16 0, i16 3, i16 0, i16 0, i16 0, i16 4, i16 0, i16 0, i16 0>, <8 x i16> %4)
|
||||
%6 = bitcast <16 x i16> %5 to <8 x i32>
|
||||
%7 = bitcast <2 x i64> %3 to <4 x i32>
|
||||
%8 = tail call <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32> %6, <4 x i32> %7)
|
||||
%9 = bitcast <8 x i32> %8 to <4 x i64>
|
||||
%10 = tail call <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64> %9, <2 x i64> %3)
|
||||
%11 = bitcast <4 x i64> %10 to <16 x i16>
|
||||
%12 = tail call <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16> %11, i32 %S)
|
||||
%13 = bitcast <16 x i16> %12 to <8 x i32>
|
||||
%14 = tail call <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32> %13, i32 %S)
|
||||
%15 = bitcast <8 x i32> %14 to <4 x i64>
|
||||
%16 = tail call <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64> %15, i32 %S)
|
||||
ret <4 x i64> %16
|
||||
; CHECK: test_avx2_0
|
||||
; CHECK: ret <4 x i64> zeroinitializer
|
||||
}
|
||||
|
||||
declare <4 x i64> @llvm.x86.avx2.pslli.q(<4 x i64>, i32) #1
|
||||
declare <8 x i32> @llvm.x86.avx2.pslli.d(<8 x i32>, i32) #1
|
||||
declare <16 x i16> @llvm.x86.avx2.pslli.w(<16 x i16>, i32) #1
|
||||
declare <4 x i64> @llvm.x86.avx2.psll.q(<4 x i64>, <2 x i64>) #1
|
||||
declare <8 x i32> @llvm.x86.avx2.psll.d(<8 x i32>, <4 x i32>) #1
|
||||
declare <16 x i16> @llvm.x86.avx2.psll.w(<16 x i16>, <8 x i16>) #1
|
||||
declare <2 x i64> @llvm.x86.sse2.pslli.q(<2 x i64>, i32) #1
|
||||
declare <4 x i32> @llvm.x86.sse2.pslli.d(<4 x i32>, i32) #1
|
||||
declare <8 x i16> @llvm.x86.sse2.pslli.w(<8 x i16>, i32) #1
|
||||
declare <2 x i64> @llvm.x86.sse2.psll.q(<2 x i64>, <2 x i64>) #1
|
||||
declare <4 x i32> @llvm.x86.sse2.psll.d(<4 x i32>, <4 x i32>) #1
|
||||
declare <8 x i16> @llvm.x86.sse2.psll.w(<8 x i16>, <8 x i16>) #1
|
||||
|
||||
attributes #1 = { nounwind readnone }
|
||||
|
Loading…
Reference in New Issue
Block a user