diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index a3b2e62a1b8ba..872d1725b6bee 100755 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -2165,16 +2165,13 @@ Constant *constantFoldVectorReduce(Intrinsic::ID IID, Constant *Op) { return PoisonValue::get(VT->getElementType()); // TODO: Handle undef. - if (!isa(Op) && !isa(Op)) - return nullptr; - - auto *EltC = dyn_cast(Op->getAggregateElement(0U)); + auto *EltC = dyn_cast_or_null(Op->getAggregateElement(0U)); if (!EltC) return nullptr; APInt Acc = EltC->getValue(); for (unsigned I = 1, E = VT->getNumElements(); I != E; I++) { - if (!(EltC = dyn_cast(Op->getAggregateElement(I)))) + if (!(EltC = dyn_cast_or_null(Op->getAggregateElement(I)))) return nullptr; const APInt &X = EltC->getValue(); switch (IID) { @@ -3040,35 +3037,25 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, Val = Val | Val << 1; return ConstantInt::get(Ty, Val); } - - default: - return nullptr; } } - switch (IntrinsicID) { - default: break; - case Intrinsic::vector_reduce_add: - case Intrinsic::vector_reduce_mul: - case Intrinsic::vector_reduce_and: - case Intrinsic::vector_reduce_or: - case Intrinsic::vector_reduce_xor: - case Intrinsic::vector_reduce_smin: - case Intrinsic::vector_reduce_smax: - case Intrinsic::vector_reduce_umin: - case Intrinsic::vector_reduce_umax: - if (Constant *C = constantFoldVectorReduce(IntrinsicID, Operands[0])) - return C; - break; - } - - // Support ConstantVector in case we have an Undef in the top. - if (isa(Operands[0]) || - isa(Operands[0]) || - isa(Operands[0])) { + if (Operands[0]->getType()->isVectorTy()) { auto *Op = cast(Operands[0]); switch (IntrinsicID) { default: break; + case Intrinsic::vector_reduce_add: + case Intrinsic::vector_reduce_mul: + case Intrinsic::vector_reduce_and: + case Intrinsic::vector_reduce_or: + case Intrinsic::vector_reduce_xor: + case Intrinsic::vector_reduce_smin: + case Intrinsic::vector_reduce_smax: + case Intrinsic::vector_reduce_umin: + case Intrinsic::vector_reduce_umax: + if (Constant *C = constantFoldVectorReduce(IntrinsicID, Operands[0])) + return C; + break; case Intrinsic::x86_sse_cvtss2si: case Intrinsic::x86_sse_cvtss2si64: case Intrinsic::x86_sse2_cvtsd2si: @@ -3096,6 +3083,9 @@ static Constant *ConstantFoldScalarCall1(StringRef Name, case Intrinsic::wasm_alltrue: // Check each element individually + if (!isa(Op)) + break; unsigned E = cast(Op->getType())->getNumElements(); for (unsigned I = 0; I != E; ++I) if (Constant *Elt = Op->getAggregateElement(I)) diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/any_all_true.ll b/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/any_all_true.ll index 7b30edbf7792b..71dad41b971b5 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/any_all_true.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/WebAssembly/any_all_true.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 ; RUN: opt -passes=instsimplify -S < %s | FileCheck %s +; RUN: opt -passes=instsimplify -use-constant-int-for-fixed-length-splat -S < %s | FileCheck %s ; Test that intrinsics wasm call are constant folded diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/bitcount.ll b/llvm/test/Transforms/InstSimplify/ConstProp/bitcount.ll index 68b45a94af4bc..f68b85ed4db26 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/bitcount.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/bitcount.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s +; RUN: opt < %s -passes=instsimplify -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat -S | FileCheck %s declare i31 @llvm.ctpop.i31(i31 %val) declare i32 @llvm.cttz.i32(i32 %val, i1) @@ -120,6 +121,22 @@ define <2 x i31> @ctpop_vector() { ret <2 x i31> %x } +define <2 x i31> @ctpop_vector_splat_v2i31() { +; CHECK-LABEL: @ctpop_vector_splat_v2i31( +; CHECK-NEXT: ret <2 x i31> splat (i31 1) +; + %x = call <2 x i31> @llvm.ctpop.v2i31(<2 x i31> splat(i31 16)) + ret <2 x i31> %x +} + +define @ctpop_vector_splat_nxv2i31() { +; CHECK-LABEL: @ctpop_vector_splat_nxv2i31( +; CHECK-NEXT: ret splat (i31 1) +; + %x = call @llvm.ctpop.nxv2i31( splat(i31 16)) + ret %x +} + define <2 x i31> @ctpop_vector_undef() { ; CHECK-LABEL: @ctpop_vector_undef( ; CHECK-NEXT: ret <2 x i31> zeroinitializer diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/bitreverse.ll b/llvm/test/Transforms/InstSimplify/ConstProp/bitreverse.ll new file mode 100644 index 0000000000000..409141a2c872b --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/ConstProp/bitreverse.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6 +; RUN: opt < %s -passes=instsimplify -S | FileCheck %s +; RUN: opt < %s -passes=instsimplify -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat -S | FileCheck %s + +define i16 @W() { +; CHECK-LABEL: define i16 @W() { +; CHECK-NEXT: ret i16 -32768 +; + %Z = call i16 @llvm.bitreverse.i16(i16 1) + ret i16 %Z +} + +define i32 @X() { +; CHECK-LABEL: define i32 @X() { +; CHECK-NEXT: ret i32 -2147483648 +; + %Z = call i32 @llvm.bitreverse.i32(i32 1) + ret i32 %Z +} + +define i64 @Y() { +; CHECK-LABEL: define i64 @Y() { +; CHECK-NEXT: ret i64 -9223372036854775808 +; + %Z = call i64 @llvm.bitreverse.i64(i64 1) + ret i64 %Z +} + +define i80 @Z() { +; CHECK-LABEL: define i80 @Z() { +; CHECK-NEXT: ret i80 23777929115895377691656 +; + %Z = call i80 @llvm.bitreverse.i80(i80 76151636403560493650080) + ret i80 %Z +} + +define <4 x i32> @bitreverse_splat_v4i32() { +; CHECK-LABEL: define <4 x i32> @bitreverse_splat_v4i32() { +; CHECK-NEXT: ret <4 x i32> splat (i32 -2147483648) +; + %Z = call <4 x i32> @llvm.bitreverse.v4i32(<4 x i32> splat(i32 1)) + ret <4 x i32> %Z +} + +define @bitreverse_splat_nxv4i32() { +; CHECK-LABEL: define @bitreverse_splat_nxv4i32() { +; CHECK-NEXT: ret splat (i32 -2147483648) +; + %Z = call @llvm.bitreverse.v4i32( splat(i32 1)) + ret %Z +} diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/bswap.ll b/llvm/test/Transforms/InstSimplify/ConstProp/bswap.ll index 42bb73344995b..4db8ced58327a 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/bswap.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/bswap.ll @@ -2,6 +2,7 @@ ; bswap should be constant folded when it is passed a constant argument ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s +; RUN: opt < %s -passes=instsimplify -use-constant-int-for-fixed-length-splat -use-constant-int-for-scalable-splat -S | FileCheck %s declare i16 @llvm.bswap.i16(i16) @@ -42,3 +43,19 @@ define i80 @Z() { %Z = call i80 @llvm.bswap.i80( i80 76151636403560493650080 ) ret i80 %Z } + +define <4 x i32> @bswap_splat_v4i32() { +; CHECK-LABEL: define <4 x i32> @bswap_splat_v4i32() { +; CHECK-NEXT: ret <4 x i32> splat (i32 16777216) +; + %Z = call <4 x i32> @llvm.bswap.v4i32(<4 x i32> splat(i32 1)) + ret <4 x i32> %Z +} + +define @bswap_splat_nxv4i32() { +; CHECK-LABEL: define @bswap_splat_nxv4i32() { +; CHECK-NEXT: ret splat (i32 16777216) +; + %Z = call @llvm.bswap.v4i32( splat(i32 1)) + ret %Z +} diff --git a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll index e994921f62574..9f9e3f9ffc070 100644 --- a/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll +++ b/llvm/test/Transforms/InstSimplify/ConstProp/vecreduce.ll @@ -1,5 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s +; RUN: opt < %s -passes=instsimplify -use-constant-int-for-fixed-length-splat -S | FileCheck %s declare i32 @llvm.vector.reduce.add.v1i32(<1 x i32> %a) declare i32 @llvm.vector.reduce.add.v8i32(<8 x i32> %a)