From: Andrea Di Biagio Date: Wed, 7 Sep 2016 12:03:03 +0000 (+0000) Subject: [InstCombine][SSE4a] Fix assertion failure caused by unsafe dyn_casts on the operands... X-Git-Tag: llvmorg-4.0.0-rc1~10467 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8df5b9cf487701ff323d3a758c71349f8b7916a8;p=platform%2Fupstream%2Fllvm.git [InstCombine][SSE4a] Fix assertion failure caused by unsafe dyn_casts on the operands of extrq/extrqi intrinsic calls. This patch fixes an assertion failure caused by unsafe dynamic casts on the constant operands of sse4a intrinsic calls to extrq/extrqi The combine logic that simplifies sse4a extrq/extrqi intrinsic calls currently checks if the input operands are constants. Internally, that logic relies on dyn_casts of values returned by calls to method Constant::getAggregateElement. However, method getAggregateElemet may return nullptr if the constant element cannot be retrieved. So, all the dyn_casts can potentially fail. This is what happens for example if a constexpr value is passed in input to an extrq/extrqi intrinsic call. This patch fixes the problem by using a dyn_cast_or_null (instead of a simple dyn_cast) on the result of each call to Constant::getAggregateElement. Added reproducible test cases to x86-sse4a.ll. Differential Revision: https://reviews.llvm.org/D24256 llvm-svn: 280804 --- diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 15069e6..eb334442 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -584,7 +584,7 @@ static Value *simplifyX86extrq(IntrinsicInst &II, Value *Op0, // See if we're dealing with constant values. Constant *C0 = dyn_cast(Op0); ConstantInt *CI0 = - C0 ? dyn_cast(C0->getAggregateElement((unsigned)0)) + C0 ? dyn_cast_or_null(C0->getAggregateElement((unsigned)0)) : nullptr; // Attempt to constant fold. @@ -1856,10 +1856,10 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // See if we're dealing with constant values. Constant *C1 = dyn_cast(Op1); ConstantInt *CILength = - C1 ? dyn_cast(C1->getAggregateElement((unsigned)0)) + C1 ? dyn_cast_or_null(C1->getAggregateElement((unsigned)0)) : nullptr; ConstantInt *CIIndex = - C1 ? dyn_cast(C1->getAggregateElement((unsigned)1)) + C1 ? dyn_cast_or_null(C1->getAggregateElement((unsigned)1)) : nullptr; // Attempt to simplify to a constant, shuffle vector or EXTRQI call. diff --git a/llvm/test/Transforms/InstCombine/x86-sse4a.ll b/llvm/test/Transforms/InstCombine/x86-sse4a.ll index 53353ab..e135c38 100644 --- a/llvm/test/Transforms/InstCombine/x86-sse4a.ll +++ b/llvm/test/Transforms/InstCombine/x86-sse4a.ll @@ -55,6 +55,15 @@ define <2 x i64> @test_extrq_constant_undef(<2 x i64> %x, <16 x i8> %y) { ret <2 x i64> %1 } +define <2 x i64> @test_extrq_call_constexpr(<2 x i64> %x) { +; CHECK-LABEL: @test_extrq_call_constexpr( +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> bitcast (<2 x i64> to <16 x i8>)) +; CHECK-NEXT: ret <2 x i64> [[TMP1]] +; + %1 = call <2 x i64> @llvm.x86.sse4a.extrq(<2 x i64> %x, <16 x i8> bitcast (<2 x i64> to <16 x i8>)) + ret <2 x i64> %1 +} + ; ; EXTRQI ; @@ -122,6 +131,14 @@ define <2 x i64> @test_extrqi_constant_undef(<2 x i64> %x) { ret <2 x i64> %1 } +define <2 x i64> @test_extrqi_call_constexpr() { +; CHECK-LABEL: @test_extrqi_call_constexpr( +; CHECK-NEXT: ret <2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> to <16 x i16>) to <16 x i8>), i32 2), i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 0, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef, i8 undef> to <2 x i64>) +; + %1 = tail call <2 x i64> @llvm.x86.sse4a.extrqi(<2 x i64> bitcast (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> to <16 x i16>) to <16 x i8>) to <2 x i64>), i8 8, i8 16) + ret <2 x i64> %1 +} + ; ; INSERTQ ;