| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s |
| |
| define i1 @idx_known_positive_via_len_1(i8 %len, i8 %idx) { |
| ; CHECK-LABEL: @idx_known_positive_via_len_1( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[LEN_POS:%.*]] = icmp sge i8 [[LEN:%.*]], 0 |
| ; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN]] |
| ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[LEN_POS]], [[IDX_ULT_LEN]] |
| ; CHECK-NEXT: br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then.1: |
| ; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true |
| ; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[IDX]], 1 |
| ; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_1]] |
| ; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], true |
| ; CHECK-NEXT: ret i1 [[R_3]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: ret i1 [[C_3]] |
| ; |
| entry: |
| %len.pos = icmp sge i8 %len, 0 |
| %idx.ult.len = icmp ult i8 %idx, %len |
| %and.1 = and i1 %len.pos, %idx.ult.len |
| br i1 %and.1, label %then.1, label %else |
| |
| then.1: |
| %t.1 = icmp ult i8 %idx, %len |
| %t.2 = icmp sge i8 %idx, 0 |
| %r.1 = xor i1 %t.1, %t.2 |
| |
| %c.1 = icmp sge i8 %idx, 1 |
| %r.2 = xor i1 %r.1, %c.1 |
| |
| %c.2 = icmp sge i8 %len, 1 |
| %r.3 = xor i1 %r.2, %c.2 |
| ret i1 %r.3 |
| |
| else: |
| %c.3 = icmp sge i8 %idx, 0 |
| ret i1 %c.3 |
| } |
| |
| ; Like @idx_known_positive_via_len_1, but with a different order of known facts. |
| define i1 @idx_known_positive_via_len_2(i8 %len, i8 %idx) { |
| ; CHECK-LABEL: @idx_known_positive_via_len_2( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN:%.*]] |
| ; CHECK-NEXT: [[LEN_POS:%.*]] = icmp sge i8 [[LEN]], 0 |
| ; CHECK-NEXT: [[AND_1:%.*]] = and i1 [[IDX_ULT_LEN]], [[LEN_POS]] |
| ; CHECK-NEXT: br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then.1: |
| ; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, true |
| ; CHECK-NEXT: [[C_1:%.*]] = icmp sge i8 [[IDX]], 1 |
| ; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_1]] |
| ; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], true |
| ; CHECK-NEXT: ret i1 [[R_3]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: ret i1 [[C_3]] |
| ; |
| entry: |
| %idx.ult.len = icmp ult i8 %idx, %len |
| %len.pos = icmp sge i8 %len, 0 |
| %and.1 = and i1 %idx.ult.len, %len.pos |
| br i1 %and.1, label %then.1, label %else |
| |
| then.1: |
| %t.1 = icmp ult i8 %idx, %len |
| %t.2 = icmp sge i8 %idx, 0 |
| %r.1 = xor i1 %t.1, %t.2 |
| |
| %c.1 = icmp sge i8 %idx, 1 |
| %r.2 = xor i1 %r.1, %c.1 |
| |
| %c.2 = icmp sge i8 %len, 1 |
| %r.3 = xor i1 %r.2, %c.2 |
| ret i1 %r.3 |
| |
| else: |
| %c.3 = icmp sge i8 %idx, 0 |
| ret i1 %c.3 |
| } |
| |
| |
| ; %len >=u 0 is not enough to determine idx >=s 0. |
| define i1 @idx_not_known_positive_via_len_uge(i8 %len, i8 %idx) { |
| ; CHECK-LABEL: @idx_not_known_positive_via_len_uge( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN:%.*]] |
| ; CHECK-NEXT: [[AND_1:%.*]] = and i1 true, [[IDX_ULT_LEN]] |
| ; CHECK-NEXT: br i1 [[AND_1]], label [[THEN_1:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then.1: |
| ; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, [[C_2]] |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 1 |
| ; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_3]] |
| ; CHECK-NEXT: [[C_4:%.*]] = icmp sge i8 [[LEN]], 1 |
| ; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_4]] |
| ; CHECK-NEXT: ret i1 [[R_3]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_5:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: ret i1 [[C_5]] |
| ; |
| entry: |
| %len.pos = icmp uge i8 %len, 0 |
| %idx.ult.len = icmp ult i8 %idx, %len |
| %and.1 = and i1 %len.pos, %idx.ult.len |
| br i1 %and.1, label %then.1, label %else |
| |
| then.1: |
| %c.1 = icmp ult i8 %idx, %len |
| %c.2 = icmp sge i8 %idx, 0 |
| %r.1 = xor i1 %c.1, %c.2 |
| |
| %c.3 = icmp sge i8 %idx, 1 |
| %r.2 = xor i1 %r.1, %c.3 |
| |
| %c.4 = icmp sge i8 %len, 1 |
| %r.3 = xor i1 %r.2, %c.4 |
| ret i1 %r.3 |
| |
| else: |
| %c.5 = icmp sge i8 %idx, 0 |
| ret i1 %c.5 |
| } |
| |
| ; There's no information about %len which could be used to determine %len >=s 0. |
| define i1 @idx_not_known_positive_via_len(i8 %len, i8 %idx) { |
| ; CHECK-LABEL: @idx_not_known_positive_via_len( |
| ; CHECK-NEXT: entry: |
| ; CHECK-NEXT: [[IDX_ULT_LEN:%.*]] = icmp ult i8 [[IDX:%.*]], [[LEN:%.*]] |
| ; CHECK-NEXT: br i1 [[IDX_ULT_LEN]], label [[THEN_1:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then.1: |
| ; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: [[R_1:%.*]] = xor i1 true, [[C_2]] |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp sge i8 [[IDX]], 1 |
| ; CHECK-NEXT: [[R_2:%.*]] = xor i1 [[R_1]], [[C_3]] |
| ; CHECK-NEXT: [[C_4:%.*]] = icmp sge i8 [[LEN]], 1 |
| ; CHECK-NEXT: [[R_3:%.*]] = xor i1 [[R_2]], [[C_4]] |
| ; CHECK-NEXT: ret i1 [[R_3]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_5:%.*]] = icmp sge i8 [[IDX]], 0 |
| ; CHECK-NEXT: ret i1 [[C_5]] |
| ; |
| entry: |
| %idx.ult.len = icmp ult i8 %idx, %len |
| br i1 %idx.ult.len, label %then.1, label %else |
| |
| then.1: |
| %c.1 = icmp ult i8 %idx, %len |
| %c.2 = icmp sge i8 %idx, 0 |
| %r.1 = xor i1 %c.1, %c.2 |
| |
| %c.3 = icmp sge i8 %idx, 1 |
| %r.2 = xor i1 %r.1, %c.3 |
| |
| %c.4 = icmp sge i8 %len, 1 |
| %r.3 = xor i1 %r.2, %c.4 |
| ret i1 %r.3 |
| |
| else: |
| %c.5 = icmp sge i8 %idx, 0 |
| ret i1 %c.5 |
| } |
| |
| define i1 @ult_signed_pos_constant(i8 %a) { |
| ; CHECK-LABEL: @ult_signed_pos_constant( |
| ; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp ult i8 [[A:%.*]], 4 |
| ; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true |
| ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true |
| ; CHECK-NEXT: ret i1 [[RES_2]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[A]], 0 |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp slt i8 [[A]], 4 |
| ; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[C_2]], [[C_3]] |
| ; CHECK-NEXT: [[C_4:%.*]] = icmp slt i8 [[A]], 5 |
| ; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_4]] |
| ; CHECK-NEXT: ret i1 [[RES_4]] |
| ; |
| %a.ult.4 = icmp ult i8 %a, 4 |
| br i1 %a.ult.4, label %then, label %else |
| |
| then: |
| %t.0 = icmp sge i8 %a, 0 |
| %t.1 = icmp slt i8 %a, 4 |
| %res.1 = xor i1 %t.0, %t.1 |
| |
| %c.0 = icmp slt i8 %a, 5 |
| %res.2 = xor i1 %res.1, %c.0 |
| ret i1 %res.2 |
| |
| else: |
| %c.2 = icmp sge i8 %a, 0 |
| %c.3 = icmp slt i8 %a, 4 |
| %res.3 = xor i1 %c.2, %c.3 |
| |
| %c.4 = icmp slt i8 %a, 5 |
| %res.4 = xor i1 %res.3, %c.4 |
| |
| ret i1 %res.4 |
| } |
| |
| define i1 @ult_signed_neg_constant(i8 %a) { |
| ; CHECK-LABEL: @ult_signed_neg_constant( |
| ; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp ult i8 [[A:%.*]], -2 |
| ; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[C_0:%.*]] = icmp sge i8 [[A]], 0 |
| ; CHECK-NEXT: [[C_1:%.*]] = icmp slt i8 [[A]], -2 |
| ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 [[C_0]], [[C_1]] |
| ; CHECK-NEXT: ret i1 [[RES_1]] |
| ; CHECK: else: |
| ; CHECK-NEXT: ret i1 false |
| ; |
| %a.ult.4 = icmp ult i8 %a, -2 |
| br i1 %a.ult.4, label %then, label %else |
| |
| then: |
| %c.0 = icmp sge i8 %a, 0 |
| %c.1 = icmp slt i8 %a, -2 |
| %res.1 = xor i1 %c.0, %c.1 |
| ret i1 %res.1 |
| |
| else: |
| ret i1 0 |
| } |
| |
| define i1 @ule_signed_pos_constant_1(i8 %a, i8 %b) { |
| ; CHECK-LABEL: @ule_signed_pos_constant_1( |
| ; CHECK-NEXT: [[B_NON_NEG:%.*]] = icmp sge i8 [[B:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[B_NON_NEG]]) |
| ; CHECK-NEXT: [[A_ULE_B:%.*]] = icmp ule i8 [[A:%.*]], [[B]] |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A_ULE_B]]) |
| ; CHECK-NEXT: [[SLT_TEST:%.*]] = icmp slt i8 [[A]], [[B]] |
| ; CHECK-NEXT: [[RESULT_XOR:%.*]] = xor i1 true, [[SLT_TEST]] |
| ; CHECK-NEXT: ret i1 [[RESULT_XOR]] |
| ; |
| %b_non_neg = icmp sge i8 %b, 0 |
| call void @llvm.assume(i1 %b_non_neg) |
| %a_ule_b = icmp ule i8 %a, %b |
| call void @llvm.assume(i1 %a_ule_b) |
| |
| %sle_test = icmp sle i8 %a, %b |
| %slt_test = icmp slt i8 %a, %b |
| %result_xor = xor i1 %sle_test, %slt_test |
| |
| ret i1 %result_xor |
| } |
| |
| define i1 @ule_signed_pos_constant_2(i8 %a) { |
| ; CHECK-LABEL: @ule_signed_pos_constant_2( |
| ; CHECK-NEXT: [[A_ULT_4:%.*]] = icmp ule i8 [[A:%.*]], 4 |
| ; CHECK-NEXT: br i1 [[A_ULT_4]], label [[THEN:%.*]], label [[ELSE:%.*]] |
| ; CHECK: then: |
| ; CHECK-NEXT: [[RES_1:%.*]] = xor i1 true, true |
| ; CHECK-NEXT: [[RES_2:%.*]] = xor i1 [[RES_1]], true |
| ; CHECK-NEXT: ret i1 [[RES_2]] |
| ; CHECK: else: |
| ; CHECK-NEXT: [[C_2:%.*]] = icmp sge i8 [[A]], 0 |
| ; CHECK-NEXT: [[C_3:%.*]] = icmp sle i8 [[A]], 4 |
| ; CHECK-NEXT: [[RES_3:%.*]] = xor i1 [[C_2]], [[C_3]] |
| ; CHECK-NEXT: [[C_4:%.*]] = icmp sle i8 [[A]], 5 |
| ; CHECK-NEXT: [[RES_4:%.*]] = xor i1 [[RES_3]], [[C_4]] |
| ; CHECK-NEXT: ret i1 [[RES_4]] |
| ; |
| %a.ult.4 = icmp ule i8 %a, 4 |
| br i1 %a.ult.4, label %then, label %else |
| |
| then: |
| %t.0 = icmp sge i8 %a, 0 |
| %t.1 = icmp sle i8 %a, 4 |
| %res.1 = xor i1 %t.0, %t.1 |
| |
| %c.0 = icmp sle i8 %a, 5 |
| %res.2 = xor i1 %res.1, %c.0 |
| ret i1 %res.2 |
| |
| else: |
| %c.2 = icmp sge i8 %a, 0 |
| %c.3 = icmp sle i8 %a, 4 |
| %res.3 = xor i1 %c.2, %c.3 |
| |
| %c.4 = icmp sle i8 %a, 5 |
| %res.4 = xor i1 %res.3, %c.4 |
| |
| ret i1 %res.4 |
| } |
| |
| define i1 @uge_assumed_positive_values(i8 %a, i8 %b) { |
| ; CHECK-LABEL: @uge_assumed_positive_values( |
| ; CHECK-NEXT: [[A_NON_NEG:%.*]] = icmp sge i8 [[A:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A_NON_NEG]]) |
| ; CHECK-NEXT: [[A_UGT_B:%.*]] = icmp uge i8 [[A]], [[B:%.*]] |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A_UGT_B]]) |
| ; CHECK-NEXT: ret i1 true |
| ; |
| %a_non_neg = icmp sge i8 %a, 0 |
| call void @llvm.assume(i1 %a_non_neg) |
| %a_ugt_b = icmp uge i8 %a, %b |
| call void @llvm.assume(i1 %a_ugt_b) |
| |
| %result = icmp sge i8 %a, %b |
| |
| ret i1 %result |
| } |
| |
| define i1 @ugt_assumed_positive_values(i8 %a, i8 %b) { |
| ; CHECK-LABEL: @ugt_assumed_positive_values( |
| ; CHECK-NEXT: [[A_NON_NEG:%.*]] = icmp sge i8 [[A:%.*]], 0 |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A_NON_NEG]]) |
| ; CHECK-NEXT: [[A_UGT_B:%.*]] = icmp ugt i8 [[A]], [[B:%.*]] |
| ; CHECK-NEXT: call void @llvm.assume(i1 [[A_UGT_B]]) |
| ; CHECK-NEXT: ret i1 true |
| ; |
| %a_non_neg = icmp sge i8 %a, 0 |
| call void @llvm.assume(i1 %a_non_neg) |
| %a_ugt_b = icmp ugt i8 %a, %b |
| call void @llvm.assume(i1 %a_ugt_b) |
| |
| %result = icmp sgt i8 %a, %b |
| |
| ret i1 %result |
| } |
| |
| declare void @llvm.assume(i1) |