Skip to content

Commit

Permalink
[InstCombine][SSE4a] Fix assertion failure caused by unsafe dyn_casts…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
Andrea Di Biagio authored and Andrea Di Biagio committed Sep 7, 2016
1 parent bcbbb39 commit 8df5b9c
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 3 deletions.
6 changes: 3 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Expand Up @@ -584,7 +584,7 @@ static Value *simplifyX86extrq(IntrinsicInst &II, Value *Op0,
// See if we're dealing with constant values.
Constant *C0 = dyn_cast<Constant>(Op0);
ConstantInt *CI0 =
C0 ? dyn_cast<ConstantInt>(C0->getAggregateElement((unsigned)0))
C0 ? dyn_cast_or_null<ConstantInt>(C0->getAggregateElement((unsigned)0))
: nullptr;

// Attempt to constant fold.
Expand Down Expand Up @@ -1856,10 +1856,10 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) {
// See if we're dealing with constant values.
Constant *C1 = dyn_cast<Constant>(Op1);
ConstantInt *CILength =
C1 ? dyn_cast<ConstantInt>(C1->getAggregateElement((unsigned)0))
C1 ? dyn_cast_or_null<ConstantInt>(C1->getAggregateElement((unsigned)0))
: nullptr;
ConstantInt *CIIndex =
C1 ? dyn_cast<ConstantInt>(C1->getAggregateElement((unsigned)1))
C1 ? dyn_cast_or_null<ConstantInt>(C1->getAggregateElement((unsigned)1))
: nullptr;

// Attempt to simplify to a constant, shuffle vector or EXTRQI call.
Expand Down
17 changes: 17 additions & 0 deletions llvm/test/Transforms/InstCombine/x86-sse4a.ll
Expand Up @@ -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> <i64 0, i64 undef> 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> <i64 0, i64 undef> to <16 x i8>))
ret <2 x i64> %1
}

;
; EXTRQI
;
Expand Down Expand Up @@ -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> <i8 extractelement (<16 x i8> trunc (<16 x i16> bitcast (<4 x i64> <i64 0, i64 undef, i64 2, i64 undef> 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> <i64 0, i64 undef, i64 2, i64 undef> to <16 x i16>) to <16 x i8>) to <2 x i64>), i8 8, i8 16)
ret <2 x i64> %1
}

;
; INSERTQ
;
Expand Down

0 comments on commit 8df5b9c

Please sign in to comment.