Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -6472,14 +6472,14 @@ ^^^^^^^^^^^^^^^^^^^^ ``range`` metadata may be attached only to ``load``, ``call`` and ``invoke`` of -integer types. It expresses the possible ranges the loaded value or the value -returned by the called function at this call site is in. If the loaded or -returned value is not in the specified range, a poison value is returned -instead. The ranges are represented with a flattened list of integers. The -loaded value or the value returned is known to be in the union of the ranges +integer or vector of integer types. It expresses the possible ranges the loaded +value or the value returned by the called function at this call site is in. If +the loaded or returned value is not in the specified range, a poison value is +returned instead. The ranges are represented with a flattened list of integers. +The loaded value or the value returned is known to be in the union of the ranges defined by each consecutive pair. Each pair has the following properties: -- The type must match the type loaded by the instruction. +- The type must match the scalar type of the instruction. - The pair ``a,b`` represents the range ``[a,b)``. - Both ``a`` and ``b`` are constants. - The range is allowed to wrap. @@ -6489,6 +6489,8 @@ In addition, the pairs must be in signed order of the lower bound and they must be non-contiguous. +For vector-typed instructions, the range is applied element-wise. + Examples: .. code-block:: llvm @@ -6498,6 +6500,7 @@ %c = call i8 @foo(), !range !2 ; Can only be 0, 1, 3, 4 or 5 %d = invoke i8 @bar() to label %cont unwind label %lpad, !range !3 ; Can only be -2, -1, 3, 4 or 5 + %e = load <2 x i8>, ptr %x, !range 0 ; Can only be <0 or 1, 0 or 1> ... !0 = !{ i8 0, i8 2 } !1 = !{ i8 255, i8 2 } Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -3896,7 +3896,8 @@ ConstantInt *High = mdconst::dyn_extract(Range->getOperand(2 * i + 1)); Check(High, "The upper limit must be an integer!", High); - Check(High->getType() == Low->getType() && High->getType() == Ty, + Check(High->getType() == Low->getType() && + High->getType() == Ty->getScalarType(), "Range types must match instruction type!", &I); APInt HighV = High->getValue(); Index: llvm/lib/Transforms/IPO/SCCP.cpp =================================================================== --- llvm/lib/Transforms/IPO/SCCP.cpp +++ llvm/lib/Transforms/IPO/SCCP.cpp @@ -280,7 +280,7 @@ // If there is a known constant range for the return value, add !range // metadata to the function's call sites. - if (F->getReturnType()->isIntegerTy() && ReturnValue.isConstantRange() && + if (ReturnValue.isConstantRange() && !ReturnValue.getConstantRange().isSingleElement()) { // Do not add range metadata if the return value may include undef. if (ReturnValue.isConstantRangeIncludingUndef()) Index: llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -599,8 +599,7 @@ } // Add range metadata since known bits can't completely reflect what we know. - // TODO: Handle splat vectors. - auto *IT = dyn_cast(Op0->getType()); + auto *IT = cast(Op0->getType()->getScalarType()); if (IT && IT->getBitWidth() != 1 && !II.getMetadata(LLVMContext::MD_range)) { Metadata *LowAndHigh[] = { ConstantAsMetadata::get(ConstantInt::get(IT, DefiniteZeros)), @@ -683,12 +682,8 @@ Constant::getNullValue(Ty)), Ty); - // FIXME: Try to simplify vectors of integers. - auto *IT = dyn_cast(Ty); - if (!IT) - return nullptr; - // Add range metadata since known bits can't completely reflect what we know. + auto *IT = cast(Ty->getScalarType()); unsigned MinCount = Known.countMinPopulation(); unsigned MaxCount = Known.countMaxPopulation(); if (IT->getBitWidth() != 1 && !II.getMetadata(LLVMContext::MD_range)) { Index: llvm/test/Transforms/InstCombine/ctpop.ll =================================================================== --- llvm/test/Transforms/InstCombine/ctpop.ll +++ llvm/test/Transforms/InstCombine/ctpop.ll @@ -72,14 +72,9 @@ ; Test when the number of possible known bits isn't one less than a power of 2 ; and the compare value is greater but less than the next power of 2. -; TODO: The icmp is unnecessary given the known bits of the input, but range -; metadata doesn't support vectors define <2 x i1> @test5vec(<2 x i32> %arg) { ; CHECK-LABEL: @test5vec( -; CHECK-NEXT: [[AND:%.*]] = and <2 x i32> [[ARG:%.*]], -; CHECK-NEXT: [[CNT:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[AND]]) -; CHECK-NEXT: [[RES:%.*]] = icmp eq <2 x i32> [[CNT]], -; CHECK-NEXT: ret <2 x i1> [[RES]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %and = and <2 x i32> %arg, %cnt = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %and) @@ -150,7 +145,7 @@ define <2 x i32> @_parity_of_not_vec(<2 x i32> %x) { ; CHECK-LABEL: @_parity_of_not_vec( -; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG1]] ; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[R]] ; @@ -162,7 +157,7 @@ define <2 x i32> @_parity_of_not_undef(<2 x i32> %x) { ; CHECK-LABEL: @_parity_of_not_undef( -; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]), !range [[RNG1]] ; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[TMP1]], ; CHECK-NEXT: ret <2 x i32> [[R]] ; @@ -175,7 +170,7 @@ define <2 x i32> @_parity_of_not_undef2(<2 x i32> %x) { ; CHECK-LABEL: @_parity_of_not_undef2( ; CHECK-NEXT: [[NEG:%.*]] = xor <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]]) +; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[NEG]]), !range [[RNG1]] ; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[CNT]], ; CHECK-NEXT: ret <2 x i32> [[R]] ; @@ -206,8 +201,8 @@ define i32 @ctpop_add_no_common_bits(i32 %a, i32 %b) { ; CHECK-LABEL: @ctpop_add_no_common_bits( ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.fshl.i32(i32 [[A:%.*]], i32 [[B:%.*]], i32 16) -; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP1]]), !range [[RNG1]] -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[RES:%.*]] = call i32 @llvm.ctpop.i32(i32 [[TMP1]]), !range [[RNG1]] +; CHECK-NEXT: ret i32 [[RES]] ; %shl16 = shl i32 %a, 16 %ctpop1 = tail call i32 @llvm.ctpop.i32(i32 %shl16) @@ -220,8 +215,8 @@ define <2 x i32> @ctpop_add_no_common_bits_vec(<2 x i32> %a, <2 x i32> %b) { ; CHECK-LABEL: @ctpop_add_no_common_bits_vec( ; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.fshl.v2i32(<2 x i32> [[A:%.*]], <2 x i32> [[B:%.*]], <2 x i32> ) -; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]) -; CHECK-NEXT: ret <2 x i32> [[TMP2]] +; CHECK-NEXT: [[RES:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]), !range [[RNG1]] +; CHECK-NEXT: ret <2 x i32> [[RES]] ; %shl16 = shl <2 x i32> %a, %ctpop1 = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %shl16) @@ -234,9 +229,9 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use(<2 x i32> %a, <2 x i32> %b, ptr %p) { ; CHECK-LABEL: @ctpop_add_no_common_bits_vec_use( ; CHECK-NEXT: [[SHL16:%.*]] = shl <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[CTPOP1:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHL16]]) +; CHECK-NEXT: [[CTPOP1:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHL16]]), !range [[RNG3:![0-9]+]] ; CHECK-NEXT: [[LSHL16:%.*]] = lshr <2 x i32> [[B:%.*]], -; CHECK-NEXT: [[CTPOP2:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[LSHL16]]) +; CHECK-NEXT: [[CTPOP2:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[LSHL16]]), !range [[RNG3]] ; CHECK-NEXT: store <2 x i32> [[CTPOP2]], ptr [[P:%.*]], align 8 ; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i32> [[CTPOP1]], [[CTPOP2]] ; CHECK-NEXT: ret <2 x i32> [[RES]] @@ -253,10 +248,10 @@ define <2 x i32> @ctpop_add_no_common_bits_vec_use2(<2 x i32> %a, <2 x i32> %b, ptr %p) { ; CHECK-LABEL: @ctpop_add_no_common_bits_vec_use2( ; CHECK-NEXT: [[SHL16:%.*]] = shl <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[CTPOP1:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHL16]]) +; CHECK-NEXT: [[CTPOP1:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[SHL16]]), !range [[RNG3]] ; CHECK-NEXT: store <2 x i32> [[CTPOP1]], ptr [[P:%.*]], align 8 ; CHECK-NEXT: [[LSHL16:%.*]] = lshr <2 x i32> [[B:%.*]], -; CHECK-NEXT: [[CTPOP2:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[LSHL16]]) +; CHECK-NEXT: [[CTPOP2:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[LSHL16]]), !range [[RNG3]] ; CHECK-NEXT: [[RES:%.*]] = add nuw nsw <2 x i32> [[CTPOP1]], [[CTPOP2]] ; CHECK-NEXT: ret <2 x i32> [[RES]] ; @@ -295,8 +290,8 @@ define i8 @sub_ctpop(i8 %a) { ; CHECK-LABEL: @sub_ctpop( ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[A:%.*]], -1 -; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ctpop.i8(i8 [[TMP1]]), !range [[RNG0]] -; CHECK-NEXT: ret i8 [[TMP2]] +; CHECK-NEXT: [[RES:%.*]] = call i8 @llvm.ctpop.i8(i8 [[TMP1]]), !range [[RNG0]] +; CHECK-NEXT: ret i8 [[RES]] ; %cnt = tail call i8 @llvm.ctpop.i8(i8 %a) %res = sub i8 8, %cnt @@ -328,8 +323,8 @@ define <2 x i32> @sub_ctpop_vec(<2 x i32> %a) { ; CHECK-LABEL: @sub_ctpop_vec( ; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[A:%.*]], -; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]) -; CHECK-NEXT: ret <2 x i32> [[TMP2]] +; CHECK-NEXT: [[RES:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]), !range [[RNG1]] +; CHECK-NEXT: ret <2 x i32> [[RES]] ; %cnt = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> %a) %res = sub <2 x i32> , %cnt @@ -338,7 +333,7 @@ define <2 x i32> @sub_ctpop_vec_extra_use(<2 x i32> %a, ptr %p) { ; CHECK-LABEL: @sub_ctpop_vec_extra_use( -; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[A:%.*]]) +; CHECK-NEXT: [[CNT:%.*]] = tail call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[A:%.*]]), !range [[RNG1]] ; CHECK-NEXT: store <2 x i32> [[CNT]], ptr [[P:%.*]], align 8 ; CHECK-NEXT: [[RES:%.*]] = sub nuw nsw <2 x i32> , [[CNT]] ; CHECK-NEXT: ret <2 x i32> [[RES]] @@ -351,7 +346,7 @@ define i32 @zext_ctpop(i16 %x) { ; CHECK-LABEL: @zext_ctpop( -; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG3:![0-9]+]] +; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.ctpop.i16(i16 [[X:%.*]]), !range [[RNG4:![0-9]+]] ; CHECK-NEXT: [[P:%.*]] = zext i16 [[TMP1]] to i32 ; CHECK-NEXT: ret i32 [[P]] ; @@ -362,7 +357,7 @@ define <2 x i32> @zext_ctpop_vec(<2 x i7> %x) { ; CHECK-LABEL: @zext_ctpop_vec( -; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i7> @llvm.ctpop.v2i7(<2 x i7> [[X:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i7> @llvm.ctpop.v2i7(<2 x i7> [[X:%.*]]), !range [[RNG2]] ; CHECK-NEXT: [[P:%.*]] = zext <2 x i7> [[TMP1]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[P]] ; @@ -375,7 +370,7 @@ ; CHECK-LABEL: @zext_ctpop_extra_use( ; CHECK-NEXT: [[Z:%.*]] = zext i16 [[X:%.*]] to i32 ; CHECK-NEXT: store i32 [[Z]], ptr [[Q:%.*]], align 4 -; CHECK-NEXT: [[P:%.*]] = call i32 @llvm.ctpop.i32(i32 [[Z]]), !range [[RNG4:![0-9]+]] +; CHECK-NEXT: [[P:%.*]] = call i32 @llvm.ctpop.i32(i32 [[Z]]), !range [[RNG3]] ; CHECK-NEXT: ret i32 [[P]] ; %z = zext i16 %x to i32 @@ -417,7 +412,7 @@ define <2 x i32> @parity_xor_vec(<2 x i32> %arg, <2 x i32> %arg1) { ; CHECK-LABEL: @parity_xor_vec( ; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i32> [[ARG1:%.*]], [[ARG:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]) +; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[TMP1]]), !range [[RNG1]] ; CHECK-NEXT: [[I4:%.*]] = and <2 x i32> [[TMP2]], ; CHECK-NEXT: ret <2 x i32> [[I4]] ; Index: llvm/test/Transforms/InstCombine/cttz.ll =================================================================== --- llvm/test/Transforms/InstCombine/cttz.ll +++ llvm/test/Transforms/InstCombine/cttz.ll @@ -8,8 +8,8 @@ define i32 @cttz_zext_zero_undef(i16 %x) { ; CHECK-LABEL: @cttz_zext_zero_undef( ; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true), !range [[RNG0:![0-9]+]] -; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[TZ:%.*]] = zext i16 [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[TZ]] ; %z = zext i16 %x to i32 %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true) @@ -42,9 +42,9 @@ define <2 x i64> @cttz_zext_zero_undef_vec(<2 x i32> %x) { ; CHECK-LABEL: @cttz_zext_zero_undef_vec( -; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true) -; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> -; CHECK-NEXT: ret <2 x i64> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true), !range [[RNG1]] +; CHECK-NEXT: [[TZ:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> +; CHECK-NEXT: ret <2 x i64> [[TZ]] ; %z = zext <2 x i32> %x to <2 x i64> %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %z, i1 true) @@ -54,7 +54,7 @@ define <2 x i64> @cttz_zext_zero_def_vec(<2 x i32> %x) { ; CHECK-LABEL: @cttz_zext_zero_def_vec( ; CHECK-NEXT: [[Z:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> -; CHECK-NEXT: [[TZ:%.*]] = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[Z]], i1 false) +; CHECK-NEXT: [[TZ:%.*]] = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[Z]], i1 false), !range [[RNG2:![0-9]+]] ; CHECK-NEXT: ret <2 x i64> [[TZ]] ; %z = zext <2 x i32> %x to <2 x i64> @@ -65,8 +65,8 @@ define i32 @cttz_sext_zero_undef(i16 %x) { ; CHECK-LABEL: @cttz_sext_zero_undef( ; CHECK-NEXT: [[TMP1:%.*]] = call i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true), !range [[RNG0]] -; CHECK-NEXT: [[TMP2:%.*]] = zext i16 [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[TZ:%.*]] = zext i16 [[TMP1]] to i32 +; CHECK-NEXT: ret i32 [[TZ]] ; %s = sext i16 %x to i32 %tz = call i32 @llvm.cttz.i32(i32 %s, i1 true) @@ -76,8 +76,8 @@ define i32 @cttz_sext_zero_def(i16 %x) { ; CHECK-LABEL: @cttz_sext_zero_def( ; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i32 -; CHECK-NEXT: [[TMP2:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP1]], i1 false), !range [[RNG1]] -; CHECK-NEXT: ret i32 [[TMP2]] +; CHECK-NEXT: [[TZ:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP1]], i1 false), !range [[RNG1]] +; CHECK-NEXT: ret i32 [[TZ]] ; %s = sext i16 %x to i32 %tz = call i32 @llvm.cttz.i32(i32 %s, i1 false) @@ -99,9 +99,9 @@ define <2 x i64> @cttz_sext_zero_undef_vec(<2 x i32> %x) { ; CHECK-LABEL: @cttz_sext_zero_undef_vec( -; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true) -; CHECK-NEXT: [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> -; CHECK-NEXT: ret <2 x i64> [[TMP2]] +; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true), !range [[RNG1]] +; CHECK-NEXT: [[TZ:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64> +; CHECK-NEXT: ret <2 x i64> [[TZ]] ; %s = sext <2 x i32> %x to <2 x i64> %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 true) @@ -111,8 +111,8 @@ define <2 x i64> @cttz_sext_zero_def_vec(<2 x i32> %x) { ; CHECK-LABEL: @cttz_sext_zero_def_vec( ; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64> -; CHECK-NEXT: [[TMP2:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[TMP1]], i1 false) -; CHECK-NEXT: ret <2 x i64> [[TMP2]] +; CHECK-NEXT: [[TZ:%.*]] = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[TMP1]], i1 false), !range [[RNG2]] +; CHECK-NEXT: ret <2 x i64> [[TZ]] ; %s = sext <2 x i32> %x to <2 x i64> %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false) Index: llvm/test/Transforms/SCCP/ip-add-range-to-call.ll =================================================================== --- llvm/test/Transforms/SCCP/ip-add-range-to-call.ll +++ llvm/test/Transforms/SCCP/ip-add-range-to-call.ll @@ -180,7 +180,7 @@ define <2 x i64> @ctlz_caller(<2 x i64> %arg) { ; CHECK-LABEL: @ctlz_caller( -; CHECK-NEXT: [[RES:%.*]] = call <2 x i64> @ctlz(<2 x i64> [[ARG:%.*]]) +; CHECK-NEXT: [[RES:%.*]] = call <2 x i64> @ctlz(<2 x i64> [[ARG:%.*]]), !range [[RNG2:![0-9]+]] ; CHECK-NEXT: ret <2 x i64> [[RES]] ; %res = call <2 x i64> @ctlz(<2 x i64> %arg) @@ -191,3 +191,4 @@ ; CHECK: [[RNG0]] = !{i32 0, i32 21} ; CHECK: [[RNG1]] = !{i32 500, i32 601} +; CHECK: [[RNG2]] = !{i64 0, i64 65} Index: llvm/test/Verifier/range-1.ll =================================================================== --- llvm/test/Verifier/range-1.ll +++ llvm/test/Verifier/range-1.ll @@ -147,3 +147,10 @@ } !18 = !{} ; CHECK: It should have at least one range! + +define <2 x i8> @vector_range_wrong_type(ptr %x) { + %y = load <2 x i8>, ptr %x, !range !19 + ret <2 x i8> %y +} +!19 = !{i16 0, i16 10} +; CHECK: Range types must match instruction type!