; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3
; RUN: opt -p constraint-elimination -S %s | FileCheck %s
declare void @llvm.assume(i1)
define i1 @addition_with_extra_facts_and_args_ult_i64(i64 noundef %a, i64 noundef %b, i64 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_i64(
; CHECK-SAME: i64 noundef [[A:%.*]], i64 noundef [[B:%.*]], i64 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i64 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i64 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i64 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 true
;
entry:
%cmp.a = icmp ule i64 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i64 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i64 %b, %a
%cmp.add = icmp ult i64 %add, %c
call void @llvm.assume(i1 %cmp.add)
%t = icmp ult i64 %a, %c
ret i1 %t
}
define i1 @addition_with_extra_facts_and_args_ult_1(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_1(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 true
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%t = icmp ult i16 %a, %c
ret i1 %t
}
define i1 @addition_with_extra_facts_and_args_ult_2(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_2(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 true
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%t = icmp ult i16 %b, %c
ret i1 %t
}
define i1 @addition_with_extra_facts_and_args_ult_3(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_3(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 false
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%f = icmp uge i16 %a, %c
ret i1 %f
}
define i1 @addition_with_extra_facts_and_args_ult_4(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_4(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 false
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%f = icmp uge i16 %b, %c
ret i1 %f
}
define i1 @addition_with_extra_facts_and_args_ult_5(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_5(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[A]], 10
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%cmp = icmp uge i16 %a, 10
ret i1 %cmp
}
define i1 @addition_with_extra_facts_and_args_ult_6(i16 noundef %a, i16 noundef %b, i16 noundef %c) {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_args_ult_6(
; CHECK-SAME: i16 noundef [[A:%.*]], i16 noundef [[B:%.*]], i16 noundef [[C:%.*]]) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i16 [[A]], [[B]]
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%cmp = icmp ult i16 %a, %b
ret i1 %cmp
}
declare i16 @get()
define i1 @addition_with_extra_facts_and_return_value_ult_1() {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_return_value_ult_1() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = call i16 @get()
; CHECK-NEXT: [[B:%.*]] = call i16 @get()
; CHECK-NEXT: [[C:%.*]] = call i16 @get()
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 true
;
entry:
%a = call i16 @get()
%b = call i16 @get()
%c = call i16 @get()
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%t = icmp ult i16 %a, %c
ret i1 %t
}
define i1 @addition_with_extra_facts_and_return_value_ult_2() {
; CHECK-LABEL: define i1 @addition_with_extra_facts_and_return_value_ult_2() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = call i16 @get()
; CHECK-NEXT: [[B:%.*]] = call i16 @get()
; CHECK-NEXT: [[C:%.*]] = call i16 @get()
; CHECK-NEXT: [[CMP_A:%.*]] = icmp ule i16 [[A]], 2048
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_A]])
; CHECK-NEXT: [[CMP_B:%.*]] = icmp ule i16 [[B]], 1024
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_B]])
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 false
;
entry:
%a = call i16 @get()
%b = call i16 @get()
%c = call i16 @get()
%cmp.a = icmp ule i16 %a, 2048
call void @llvm.assume(i1 %cmp.a)
%cmp.b = icmp ule i16 %b, 1024
call void @llvm.assume(i1 %cmp.b)
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%f = icmp uge i16 %a, %c
ret i1 %f
}
define i1 @addition_no_extra_facts_with_return_value_ult_1() {
; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_1() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = call i16 @get()
; CHECK-NEXT: [[B:%.*]] = call i16 @get()
; CHECK-NEXT: [[C:%.*]] = call i16 @get()
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 true
;
entry:
%a = call i16 @get()
%b = call i16 @get()
%c = call i16 @get()
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%t = icmp ult i16 %a, %c
ret i1 %t
}
define i1 @addition_no_extra_facts_with_return_value_ult_2() {
; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_2() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = call i16 @get()
; CHECK-NEXT: [[B:%.*]] = call i16 @get()
; CHECK-NEXT: [[C:%.*]] = call i16 @get()
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: ret i1 false
;
entry:
%a = call i16 @get()
%b = call i16 @get()
%c = call i16 @get()
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%f = icmp uge i16 %a, %c
ret i1 %f
}
define i1 @addition_no_extra_facts_with_return_value_ult_3() {
; CHECK-LABEL: define i1 @addition_no_extra_facts_with_return_value_ult_3() {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A:%.*]] = call i16 @get()
; CHECK-NEXT: [[B:%.*]] = call i16 @get()
; CHECK-NEXT: [[C:%.*]] = call i16 @get()
; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i16 [[B]], [[A]]
; CHECK-NEXT: [[CMP_ADD:%.*]] = icmp ult i16 [[ADD]], [[C]]
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP_ADD]])
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i16 [[A]], 9
; CHECK-NEXT: ret i1 [[CMP]]
;
entry:
%a = call i16 @get()
%b = call i16 @get()
%c = call i16 @get()
%add = add nuw nsw i16 %b, %a
%cmp.add = icmp ult i16 %add, %c
call void @llvm.assume(i1 %cmp.add)
%cmp = icmp uge i16 %a, 9
ret i1 %cmp
}
; Test for https://github.com/llvm/llvm-project/issues/63490.
define i1 @assume_x_ugt_y_plus_y_via_shl_eq(i8 %x, i8 %y) {
; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_eq(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[S:%.*]] = shl nuw i8 [[Y]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_1]])
; CHECK-NEXT: ret i1 false
;
%s = shl nuw i8 %y, 1
%c.1 = icmp ugt i8 %x, %s
tail call void @llvm.assume(i1 %c.1)
%c.2 = icmp eq i8 %x, %y
ret i1 %c.2
}
define i1 @assume_x_ugt_y_plus_y_via_shl_eq_no_nuw(i8 %x, i8 %y) {
; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_eq_no_nuw(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[S:%.*]] = shl i8 [[Y]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X]], [[Y]]
; CHECK-NEXT: ret i1 [[C_2]]
;
%s = shl i8 %y, 1
%c.1 = icmp ugt i8 %x, %s
tail call void @llvm.assume(i1 %c.1)
%c.2 = icmp eq i8 %x, %y
ret i1 %c.2
}
define i1 @assume_x_ugt_y_plus_y_via_add_eq(i8 %x, i8 %y) {
; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_add_eq(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[S:%.*]] = add nuw i8 [[Y]], [[Y]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_1]])
; CHECK-NEXT: ret i1 false
;
%s = add nuw i8 %y, %y
%c.1 = icmp ugt i8 %x, %s
tail call void @llvm.assume(i1 %c.1)
%c.2 = icmp eq i8 %x, %y
ret i1 %c.2
}
define i1 @assume_x_ugt_y_plus_y_via_add_eq_no_nuw(i8 %x, i8 %y) {
; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_add_eq_no_nuw(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[S:%.*]] = add i8 [[Y]], [[Y]]
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_1]])
; CHECK-NEXT: [[C_2:%.*]] = icmp eq i8 [[X]], [[Y]]
; CHECK-NEXT: ret i1 [[C_2]]
;
%s = add i8 %y, %y
%c.1 = icmp ugt i8 %x, %s
tail call void @llvm.assume(i1 %c.1)
%c.2 = icmp eq i8 %x, %y
ret i1 %c.2
}
define i1 @assume_x_ugt_y_plus_y_via_shl_ne(i8 %x, i8 %y) {
; CHECK-LABEL: define i1 @assume_x_ugt_y_plus_y_via_shl_ne(
; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {
; CHECK-NEXT: [[S:%.*]] = shl nuw i8 [[Y]], 1
; CHECK-NEXT: [[C_1:%.*]] = icmp ugt i8 [[X]], [[S]]
; CHECK-NEXT: tail call void @llvm.assume(i1 [[C_1]])
; CHECK-NEXT: ret i1 true
;
%s = shl nuw i8 %y, 1
%c.1 = icmp ugt i8 %x, %s
tail call void @llvm.assume(i1 %c.1)
%c.2 = icmp ne i8 %x, %y
ret i1 %c.2
}