blob: 45a08bd183575534513320ffa0e6522052ef361e [file] [edit]
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s --check-prefix=LLVM
typedef unsigned long long u64;
// Large unsigned range; high-bit upper bound must not be treated as empty.
int range_u64(u64 x) {
switch (x) {
case 1000000000000000000ULL ... 9999999999999999999ULL:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_u64
// CIR: cir.case(range, [#cir.int<1000000000000000000> : !u64i, #cir.int<9999999999999999999> : !u64i])
// LLVM-LABEL: define dso_local i32 @range_u64(
// LLVM: %[[D:.*]] = sub i64 %{{.*}}, 1000000000000000000
// LLVM-NEXT: %[[C:.*]] = icmp ule i64 %[[D]], 8999999999999999999
// LLVM-NEXT: br i1 %[[C]], label %{{.*}}, label %{{.*}}
// Small unsigned range at the top of the domain.
int range_u64_top(u64 x) {
switch (x) {
case 18446744073709551613ULL ... 18446744073709551615ULL:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_u64_top
// CIR: cir.case(range, [#cir.int<18446744073709551613> : !u64i, #cir.int<18446744073709551615> : !u64i])
// LLVM-LABEL: define dso_local i32 @range_u64_top(
// LLVM: switch i64 %{{.*}}, label %{{.*}} [
// LLVM-NEXT: i64 -3, label %[[BB:.*]]
// LLVM-NEXT: i64 -2, label %[[BB]]
// LLVM-NEXT: i64 -1, label %[[BB]]
// LLVM-NEXT: ]
// Signed range spanning negative to positive, wider than the expansion
// threshold.
int range_s32_neg(int x) {
switch (x) {
case -2000000000 ... 2000000000:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_s32_neg
// CIR: cir.case(range, [#cir.int<-2000000000> : !s32i, #cir.int<2000000000> : !s32i])
// LLVM-LABEL: define dso_local i32 @range_s32_neg(
// LLVM: %[[D:.*]] = sub i32 %{{.*}}, -2000000000
// LLVM-NEXT: %[[C:.*]] = icmp ule i32 %[[D]], -294967296
// LLVM-NEXT: br i1 %[[C]], label %{{.*}}, label %{{.*}}
// Small signed range (existing expansion path).
int range_s32_small(int x) {
switch (x) {
case 3 ... 6:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_s32_small
// CIR: cir.case(range, [#cir.int<3> : !s32i, #cir.int<6> : !s32i])
// LLVM-LABEL: define dso_local i32 @range_s32_small(
// LLVM: switch i32 %{{.*}}, label %{{.*}} [
// LLVM-NEXT: i32 3, label %[[BB:.*]]
// LLVM-NEXT: i32 4, label %[[BB]]
// LLVM-NEXT: i32 5, label %[[BB]]
// LLVM-NEXT: i32 6, label %[[BB]]
// LLVM-NEXT: ]
// Small signed range at the top of the domain: the expansion cursor must not
// run past INT_MAX.
int range_s32_top(int x) {
switch (x) {
case 2147483645 ... 2147483647:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_s32_top
// CIR: cir.case(range, [#cir.int<2147483645> : !s32i, #cir.int<2147483647> : !s32i])
// LLVM-LABEL: define dso_local i32 @range_s32_top(
// LLVM: switch i32 %{{.*}}, label %{{.*}} [
// LLVM-NEXT: i32 2147483645, label %[[BB:.*]]
// LLVM-NEXT: i32 2147483646, label %[[BB]]
// LLVM-NEXT: i32 2147483647, label %[[BB]]
// LLVM-NEXT: ]
// A range of size 64 sits just past the expansion threshold, so it lowers via
// the sub + ule range check rather than individual cases.
int range_thresh64(int x) {
switch (x) {
case 0 ... 64:
return 1;
default:
return 0;
}
}
// CIR-LABEL: cir.func {{.*}} @range_thresh64
// CIR: cir.case(range, [#cir.int<0> : !s32i, #cir.int<64> : !s32i])
// LLVM-LABEL: define dso_local i32 @range_thresh64(
// LLVM: %[[D:.*]] = sub i32 %{{.*}}, 0
// LLVM-NEXT: %[[C:.*]] = icmp ule i32 %[[D]], 64
// LLVM-NEXT: br i1 %[[C]], label %{{.*}}, label %{{.*}}