diff --git a/lib/Target/AArch64/AArch64ISelLowering.cpp b/lib/Target/AArch64/AArch64ISelLowering.cpp index 07ff0938ed2..7b77c59ed11 100644 --- a/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5584,11 +5584,12 @@ SDValue AArch64TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { assert(Op.getOpcode() == ISD::INSERT_VECTOR_ELT && "Unknown opcode!"); - // Check for non-constant lane. - if (!isa(Op.getOperand(2))) + // Check for non-constant or out of range lane. + EVT VT = Op.getOperand(0).getValueType(); + ConstantSDNode *CI = dyn_cast(Op.getOperand(2)); + if (!CI || CI->getZExtValue() >= VT.getVectorNumElements()) return SDValue(); - EVT VT = Op.getOperand(0).getValueType(); // Insertion/extraction are legal for V128 types. if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 || @@ -5616,11 +5617,12 @@ AArch64TargetLowering::LowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { assert(Op.getOpcode() == ISD::EXTRACT_VECTOR_ELT && "Unknown opcode!"); - // Check for non-constant lane. - if (!isa(Op.getOperand(1))) + // Check for non-constant or out of range lane. + EVT VT = Op.getOperand(0).getValueType(); + ConstantSDNode *CI = dyn_cast(Op.getOperand(1)); + if (!CI || CI->getZExtValue() >= VT.getVectorNumElements()) return SDValue(); - EVT VT = Op.getOperand(0).getValueType(); // Insertion/extraction are legal for V128 types. if (VT == MVT::v16i8 || VT == MVT::v8i16 || VT == MVT::v4i32 || diff --git a/test/CodeGen/AArch64/neon-scalar-copy.ll b/test/CodeGen/AArch64/neon-scalar-copy.ll index a01df3275a9..6afac315a96 100644 --- a/test/CodeGen/AArch64/neon-scalar-copy.ll +++ b/test/CodeGen/AArch64/neon-scalar-copy.ll @@ -101,3 +101,20 @@ define <1 x i64> @test_vector_copy_dup_dv2D(<1 x i64> %a, <2 x i64> %c) { ret <1 x i64> %vset_lane } +; Undefined behaviour, so we really don't care what actually gets emitted, just +; as long as we don't crash (since it could be dynamically unreachable). +define i32 @test_out_of_range_extract(<4 x i32> %vec) { +; CHECK-LABEL: test_out_of_range_extract: +; CHECK: ret + %elt = extractelement <4 x i32> %vec, i32 4 + ret i32 %elt +} + +; Undefined behaviour, so we really don't care what actually gets emitted, just +; as long as we don't crash (since it could be dynamically unreachable). +define void @test_out_of_range_insert(<4 x i32> %vec, i32 %elt) { +; CHECK-LABEL: test_out_of_range_insert: +; CHECK: ret + insertelement <4 x i32> %vec, i32 %elt, i32 4 + ret void +}