Skip to content

Commit

Permalink
[InstCombine] Swap out range metadata to range attribute for cttz/ctl…
Browse files Browse the repository at this point in the history
…z/ctpop (#88776)

Since all optimizations that use range metadata now also handle range attribute, this patch replaces writes of
range metadata for call instructions to range attributes.
  • Loading branch information
andjo403 authored Apr 24, 2024
1 parent ff57f40 commit b8f3024
Show file tree
Hide file tree
Showing 52 changed files with 515 additions and 517 deletions.
48 changes: 24 additions & 24 deletions clang/test/CodeGen/SystemZ/builtins-systemz-zvector.c
Original file line number Diff line number Diff line change
Expand Up @@ -2489,78 +2489,78 @@ void test_integer(void) {
// CHECK-ASM: vno

vuc = vec_cntlz(vsc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vclzb
vuc = vec_cntlz(vuc);
// CHECK: call <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctlz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vclzb
vus = vec_cntlz(vss);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vclzh
vus = vec_cntlz(vus);
// CHECK: call <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctlz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vclzh
vui = vec_cntlz(vsi);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vclzf
vui = vec_cntlz(vui);
// CHECK: call <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctlz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vclzf
vul = vec_cntlz(vsl);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vclzg
vul = vec_cntlz(vul);
// CHECK: call <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctlz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vclzg

vuc = vec_cnttz(vsc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vctzb
vuc = vec_cnttz(vuc);
// CHECK: call <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.cttz.v16i8(<16 x i8> %{{.*}}, i1 false)
// CHECK-ASM: vctzb
vus = vec_cnttz(vss);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vctzh
vus = vec_cnttz(vus);
// CHECK: call <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.cttz.v8i16(<8 x i16> %{{.*}}, i1 false)
// CHECK-ASM: vctzh
vui = vec_cnttz(vsi);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vctzf
vui = vec_cnttz(vui);
// CHECK: call <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.cttz.v4i32(<4 x i32> %{{.*}}, i1 false)
// CHECK-ASM: vctzf
vul = vec_cnttz(vsl);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vctzg
vul = vec_cnttz(vul);
// CHECK: call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> %{{.*}}, i1 false)
// CHECK-ASM: vctzg

vuc = vec_popcnt(vsc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopct
vuc = vec_popcnt(vuc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopct
vus = vec_popcnt(vss);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// (emulated)
vus = vec_popcnt(vus);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// (emulated)
vui = vec_popcnt(vsi);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// (emulated)
vui = vec_popcnt(vui);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// (emulated)
vul = vec_popcnt(vsl);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// (emulated)
vul = vec_popcnt(vul);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// (emulated)

vsc = vec_rl(vsc, vuc);
Expand Down
16 changes: 8 additions & 8 deletions clang/test/CodeGen/SystemZ/builtins-systemz-zvector2.c
Original file line number Diff line number Diff line change
Expand Up @@ -577,28 +577,28 @@ void test_integer(void) {
// CHECK-ASM: vnx

vuc = vec_popcnt(vsc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopctb
vuc = vec_popcnt(vuc);
// CHECK: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %{{.*}})
// CHECK-ASM: vpopctb
vus = vec_popcnt(vss);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK-ASM: vpopcth
vus = vec_popcnt(vus);
// CHECK: call <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK: call range(i16 0, 17) <8 x i16> @llvm.ctpop.v8i16(<8 x i16> %{{.*}})
// CHECK-ASM: vpopcth
vui = vec_popcnt(vsi);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK-ASM: vpopctf
vui = vec_popcnt(vui);
// CHECK: call <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK: call range(i32 0, 33) <4 x i32> @llvm.ctpop.v4i32(<4 x i32> %{{.*}})
// CHECK-ASM: vpopctf
vul = vec_popcnt(vsl);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK-ASM: vpopctg
vul = vec_popcnt(vul);
// CHECK: call <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK: call range(i64 0, 65) <2 x i64> @llvm.ctpop.v2i64(<2 x i64> %{{.*}})
// CHECK-ASM: vpopctg

vf = vec_slb(vf, vsi);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CodeGen/builtins-wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ i32x4 bitselect(i32x4 x, i32x4 y, i32x4 c) {

i8x16 popcnt(i8x16 x) {
return __builtin_wasm_popcnt_i8x16(x);
// WEBASSEMBLY: call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %x)
// WEBASSEMBLY: call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> %x)
// WEBASSEMBLY-NEXT: ret
}

Expand Down
20 changes: 10 additions & 10 deletions clang/test/CodeGen/ms-intrinsics-other.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ unsigned char test_BitScanForward(unsigned LONG *Index, unsigned LONG Mask) {
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]

Expand All @@ -70,7 +70,7 @@ unsigned char test_BitScanReverse(unsigned LONG *Index, unsigned LONG Mask) {
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -86,7 +86,7 @@ unsigned char test_BitScanForward64(unsigned LONG *Index, unsigned __int64 Mask)
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK: [[TRUNC_INDEX:%[0-9]+]] = trunc nuw nsw i64 [[INDEX]] to i32
// CHECK: store i32 [[TRUNC_INDEX]], ptr %Index, align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -101,7 +101,7 @@ unsigned char test_BitScanReverse64(unsigned LONG *Index, unsigned __int64 Mask)
// CHECK: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK: [[TRUNC_REVINDEX:%[0-9]+]] = trunc nuw nsw i64 [[REVINDEX]] to i32
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63
// CHECK: store i32 [[INDEX]], ptr %Index, align 4
Expand Down Expand Up @@ -187,47 +187,47 @@ unsigned short test__lzcnt16(unsigned short x) {
return __lzcnt16(x);
}
// CHECK: i16 @test__lzcnt16
// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 %x, i1 false)
// CHECK: ret i16 [[RESULT]]
// CHECK: }

unsigned int test__lzcnt(unsigned int x) {
return __lzcnt(x);
}
// CHECK: i32 @test__lzcnt
// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %x, i1 false)
// CHECK: ret i32 [[RESULT]]
// CHECK: }

unsigned __int64 test__lzcnt64(unsigned __int64 x) {
return __lzcnt64(x);
}
// CHECK: i64 @test__lzcnt64
// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 false)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %x, i1 false)
// CHECK: ret i64 [[RESULT]]
// CHECK: }

unsigned short test__popcnt16(unsigned short x) {
return __popcnt16(x);
}
// CHECK: i16 @test__popcnt16
// CHECK: [[RESULT:%[0-9]+]] = tail call i16 @llvm.ctpop.i16(i16 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i16 0, 17) i16 @llvm.ctpop.i16(i16 %x)
// CHECK: ret i16 [[RESULT]]
// CHECK: }

unsigned int test__popcnt(unsigned int x) {
return __popcnt(x);
}
// CHECK: i32 @test__popcnt
// CHECK: [[RESULT:%[0-9]+]] = tail call i32 @llvm.ctpop.i32(i32 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 %x)
// CHECK: ret i32 [[RESULT]]
// CHECK: }

unsigned __int64 test__popcnt64(unsigned __int64 x) {
return __popcnt64(x);
}
// CHECK: i64 @test__popcnt64
// CHECK: [[RESULT:%[0-9]+]] = tail call i64 @llvm.ctpop.i64(i64 %x)
// CHECK: [[RESULT:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctpop.i64(i64 %x)
// CHECK: ret i64 [[RESULT]]
// CHECK: }

Expand Down
8 changes: 4 additions & 4 deletions clang/test/CodeGen/ms-intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ unsigned char test_BitScanForward(unsigned long *Index, unsigned long Mask) {
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[IDXGEP:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr %Index, {{i64|i32}} 4
// CHECK: [[INDEX:%[0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 %Mask, i1 true)
// CHECK: store i32 [[INDEX]], ptr [[IDXGEP]], align 4
// CHECK: br label %[[END_LABEL]]

Expand All @@ -172,7 +172,7 @@ unsigned char test_BitScanReverse(unsigned long *Index, unsigned long Mask) {
// CHECK: ret i8 [[RESULT]]
// CHECK: [[ISNOTZERO_LABEL]]:
// CHECK: [[IDXGEP:%[a-z0-9._]+]] = getelementptr inbounds i8, ptr %Index, {{i64|i32}} 4
// CHECK: [[REVINDEX:%[0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[REVINDEX:%[0-9]+]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %Mask, i1 true)
// CHECK: [[INDEX:%[0-9]+]] = xor i32 [[REVINDEX]], 31
// CHECK: store i32 [[INDEX]], ptr [[IDXGEP]], align 4
// CHECK: br label %[[END_LABEL]]
Expand All @@ -188,7 +188,7 @@ unsigned char test_BitScanForward64(unsigned long *Index, unsigned __int64 Mask)
// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK-ARM-X64: ret i8 [[RESULT]]
// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[TRUNC_INDEX:%[0-9]+]] = trunc nuw nsw i64 [[INDEX]] to i32
// CHECK-ARM-X64: store i32 [[TRUNC_INDEX]], ptr %Index, align 4
// CHECK-ARM-X64: br label %[[END_LABEL]]
Expand All @@ -203,7 +203,7 @@ unsigned char test_BitScanReverse64(unsigned long *Index, unsigned __int64 Mask)
// CHECK-ARM-X64: [[RESULT:%[a-z0-9._]+]] = phi i8 [ 0, %[[ISZERO_LABEL:[a-z0-9._]+]] ], [ 1, %[[ISNOTZERO_LABEL]] ]
// CHECK-ARM-X64: ret i8 [[RESULT]]
// CHECK-ARM-X64: [[ISNOTZERO_LABEL]]:
// CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[REVINDEX:%[0-9]+]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %Mask, i1 true)
// CHECK-ARM-X64: [[TRUNC_REVINDEX:%[0-9]+]] = trunc nuw nsw i64 [[REVINDEX]] to i32
// CHECK-ARM-X64: [[INDEX:%[0-9]+]] = xor i32 [[TRUNC_REVINDEX]], 63
// CHECK-ARM-X64: store i32 [[INDEX]], ptr %Index, align 4
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CodeGenOpenCL/builtins-generic-amdgcn.cl
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
#pragma OPENCL EXTENSION cl_khr_fp16 : enable

// CHECK-LABEL: @test_builtin_clz(
// CHECK: tail call i32 @llvm.ctlz.i32(i32 %a, i1 true)
// CHECK: tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 %a, i1 true)
void test_builtin_clz(global int* out, int a)
{
*out = __builtin_clz(a);
}

// CHECK-LABEL: @test_builtin_clzl(
// CHECK: tail call i64 @llvm.ctlz.i64(i64 %a, i1 true)
// CHECK: tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 %a, i1 true)
void test_builtin_clzl(global long* out, long a)
{
*out = __builtin_clzl(a);
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Headers/wasm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1572,7 +1572,7 @@ uint32_t test_i8x16_bitmask(v128_t a) {
// CHECK-LABEL: @test_i8x16_popcnt(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = bitcast <4 x i32> [[A:%.*]] to <16 x i8>
// CHECK-NEXT: [[TMP1:%.*]] = tail call <16 x i8> @llvm.ctpop.v16i8(<16 x i8> [[TMP0]]), !range [[RNG5:![0-9]+]]
// CHECK-NEXT: [[TMP1:%.*]] = tail call range(i8 0, 9) <16 x i8> @llvm.ctpop.v16i8(<16 x i8> [[TMP0]])
// CHECK-NEXT: [[TMP2:%.*]] = bitcast <16 x i8> [[TMP1]] to <4 x i32>
// CHECK-NEXT: ret <4 x i32> [[TMP2]]
//
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,11 @@ class AttributeList {
addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned ArgNo,
uint64_t Bytes) const;

/// Add the range attribute to the attribute set at the return value index.
/// Returns a new list because attribute lists are immutable.
[[nodiscard]] AttributeList addRangeRetAttr(LLVMContext &C,
const ConstantRange &CR) const;

/// Add the allocsize attribute to the attribute set at the given arg index.
/// Returns a new list because attribute lists are immutable.
[[nodiscard]] AttributeList
Expand Down
5 changes: 5 additions & 0 deletions llvm/include/llvm/IR/InstrTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,11 @@ class CallBase : public Instruction {
Attrs = Attrs.addDereferenceableRetAttr(getContext(), Bytes);
}

/// adds the range attribute to the list of attributes.
void addRangeRetAttr(const ConstantRange &CR) {
Attrs = Attrs.addRangeRetAttr(getContext(), CR);
}

/// Determine whether the return value has the given attribute.
bool hasRetAttr(Attribute::AttrKind Kind) const {
return hasRetAttrImpl(Kind);
Expand Down
7 changes: 7 additions & 0 deletions llvm/lib/IR/Attributes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,13 @@ AttributeList::addDereferenceableOrNullParamAttr(LLVMContext &C, unsigned Index,
return addParamAttributes(C, Index, B);
}

AttributeList AttributeList::addRangeRetAttr(LLVMContext &C,
const ConstantRange &CR) const {
AttrBuilder B(C);
B.addRangeAttr(CR);
return addRetAttributes(C, B);
}

AttributeList AttributeList::addAllocSizeParamAttr(
LLVMContext &C, unsigned Index, unsigned ElemSizeArg,
const std::optional<unsigned> &NumElemsArg) {
Expand Down
31 changes: 13 additions & 18 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -606,14 +606,13 @@ static Instruction *foldCttzCtlz(IntrinsicInst &II, InstCombinerImpl &IC) {
return IC.replaceOperand(II, 1, IC.Builder.getTrue());
}

// Add range metadata since known bits can't completely reflect what we know.
auto *IT = cast<IntegerType>(Op0->getType()->getScalarType());
if (IT && IT->getBitWidth() != 1 && !II.getMetadata(LLVMContext::MD_range)) {
Metadata *LowAndHigh[] = {
ConstantAsMetadata::get(ConstantInt::get(IT, DefiniteZeros)),
ConstantAsMetadata::get(ConstantInt::get(IT, PossibleZeros + 1))};
II.setMetadata(LLVMContext::MD_range,
MDNode::get(II.getContext(), LowAndHigh));
// Add range attribute since known bits can't completely reflect what we know.
unsigned BitWidth = Op0->getType()->getScalarSizeInBits();
if (BitWidth != 1 && !II.hasRetAttr(Attribute::Range) &&
!II.getMetadata(LLVMContext::MD_range)) {
ConstantRange Range(APInt(BitWidth, DefiniteZeros),
APInt(BitWidth, PossibleZeros + 1));
II.addRangeRetAttr(Range);
return &II;
}

Expand Down Expand Up @@ -685,16 +684,12 @@ static Instruction *foldCtpop(IntrinsicInst &II, InstCombinerImpl &IC) {
Constant::getNullValue(Ty)),
Ty);

// Add range metadata since known bits can't completely reflect what we know.
auto *IT = cast<IntegerType>(Ty->getScalarType());
unsigned MinCount = Known.countMinPopulation();
unsigned MaxCount = Known.countMaxPopulation();
if (IT->getBitWidth() != 1 && !II.getMetadata(LLVMContext::MD_range)) {
Metadata *LowAndHigh[] = {
ConstantAsMetadata::get(ConstantInt::get(IT, MinCount)),
ConstantAsMetadata::get(ConstantInt::get(IT, MaxCount + 1))};
II.setMetadata(LLVMContext::MD_range,
MDNode::get(II.getContext(), LowAndHigh));
// Add range attribute since known bits can't completely reflect what we know.
if (BitWidth != 1 && !II.hasRetAttr(Attribute::Range) &&
!II.getMetadata(LLVMContext::MD_range)) {
ConstantRange Range(APInt(BitWidth, Known.countMinPopulation()),
APInt(BitWidth, Known.countMaxPopulation() + 1));
II.addRangeRetAttr(Range);
return &II;
}

Expand Down
Loading

0 comments on commit b8f3024

Please sign in to comment.