; RUN: opt -passes=constraint-elimination -constraint-elimination-dump-reproducers -pass-remarks=constraint-elimination %s 2>&1 | FileCheck %s target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" declare void @use(i1) declare void @llvm.assume(i1) define i1 @test_no_known_facts(ptr %dst) { ; CHECK: remark: :0:0: module; ModuleID = 'test_no_known_facts' ; CHECK-LABEL: define i1 @"{{.+}}test_no_known_factsrepro"(ptr %dst) ; CHECK-NEXT: entry: ; CHECK-NEXT: %dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0 ; CHECK-NEXT: %upper = getelementptr inbounds ptr, ptr %dst, i64 2 ; CHECK-NEXT: %c = icmp ult ptr %dst.0, %upper ; CHECK-NEXT: ret i1 %c ; CHECK-NEXT: } ; entry: %dst.0 = getelementptr inbounds ptr, ptr %dst, i64 0 %upper = getelementptr inbounds ptr, ptr %dst, i64 2 %c = icmp ult i32* %dst.0, %upper ret i1 %c } define void @test_one_known_fact_true_branch(i8 %start, i8 %high) { ; CHECK: remark: :0:0: module; ModuleID = 'test_one_known_fact_true_branch' ; CHECK-LABEL: define i1 @"{{.*}}test_one_known_fact_true_branchrepro"(i8 %high, i8 %start) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %add.ptr.i = add nuw i8 %start, 3 ; CHECK-NEXT: %0 = icmp ult i8 %add.ptr.i, %high ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %t.0 = icmp ult i8 %start, %high ; CHECK-NEXT: ret i1 %t.0 ; CHECK-NEXT: } ; entry: %add.ptr.i = add nuw i8 %start, 3 %c.1 = icmp ult i8 %add.ptr.i, %high br i1 %c.1, label %if.then, label %if.end if.then: %t.0 = icmp ult i8 %start, %high call void @use(i1 %t.0) ret void if.end: ret void } define void @test_one_known_fact_false_branch(i8 %start, i8 %high) { ; CHECK: remark: :0:0: module; ModuleID = 'test_one_known_fact_false_branch' ; ; CHECK-LABEL:define i1 @"{{.*}}test_one_known_fact_false_branchrepro"(i8 %high, i8 %start) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %add.ptr.i = add nuw i8 %start, 3 ; CHECK-NEXT: %0 = icmp ult i8 %add.ptr.i, %high ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %t.0 = icmp ult i8 %start, %high ; CHECK-NEXT: ret i1 %t.0 ; CHECK-NEXT: } ; entry: %add.ptr.i = add nuw i8 %start, 3 %c.1 = icmp uge i8 %add.ptr.i, %high br i1 %c.1, label %if.then, label %if.end if.then: ret void if.end: %t.0 = icmp ult i8 %start, %high call void @use(i1 %t.0) ret void } define void @test_multiple_known_facts_branches_1(i8 %a, i8 %b) { ; CHECK: remark: :0:0: module; ModuleID = 'test_multiple_known_facts_branches_1' ; CHECK-LABEL: define i1 @"{{.*}}test_multiple_known_facts_branches_1repro"(i8 %a, i8 %b) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp ugt i8 %a, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %1 = icmp ugt i8 %b, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %1) ; CHECK-NEXT: %add = add nuw i8 %a, %b ; CHECK-NEXT: %t.0 = icmp ugt i8 %add, 20 ; CHECK-NEXT: ret i1 %t.0 ; CHECK-NEXT: } ; entry: %c.1 = icmp ugt i8 %a, 10 br i1 %c.1, label %then.1, label %else.1 then.1: %c.2 = icmp ugt i8 %b, 10 br i1 %c.2, label %then.2, label %else.1 then.2: %add = add nuw i8 %a, %b %t.0 = icmp ugt i8 %add, 20 call void @use(i1 %t.0) ret void else.1: ret void } define void @test_multiple_known_facts_branches_2(i8 %a, i8 %b) { ; CHECK: remark: :0:0: module; ModuleID = 'test_multiple_known_facts_branches_2' ; ; CHECK-LABEL: define i1 @"{{.*}}test_multiple_known_facts_branches_2repro"(i8 %a, i8 %b) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp ugt i8 %a, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %1 = icmp ugt i8 %b, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %1) ; CHECK-NEXT: %add = add nuw i8 %a, %b ; CHECK-NEXT: %t.0 = icmp ugt i8 %add, 20 ; CHECK-NEXT: ret i1 %t.0 ; CHECK-NEXT: } ; entry: %c.1 = icmp ugt i8 %a, 10 br i1 %c.1, label %then.1, label %exit then.1: %c.2 = icmp ule i8 %b, 10 br i1 %c.2, label %exit, label %else.2 else.2: %add = add nuw i8 %a, %b %t.0 = icmp ugt i8 %add, 20 call void @use(i1 %t.0) ret void exit: ret void } define void @test_assumes(i8 %a, i8 %b) { ; CHECK-LABEL: define i1 @"{{.*}}test_assumesrepro.2"(i8 %a, i8 %b) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp ugt i8 %a, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %1 = icmp ugt i8 %b, 10 ; CHECK-NEXT: call void @llvm.assume(i1 %1) ; CHECK-NEXT: %add = add nuw i8 %a, %b ; CHECK-NEXT: %t.0 = icmp ult i8 %add, 20 ; CHECK-NEXT: ret i1 %t.0 ; CHECK-NEXT: } ; entry: %c.1 = icmp ugt i8 %a, 10 call void @llvm.assume(i1 %c.1) %c.2 = icmp ugt i8 %b, 10 call void @llvm.assume(i1 %c.2) %add = add nuw i8 %a, %b %t.0 = icmp ult i8 %add, 20 call void @use(i1 %t.0) ret void } declare void @noundef(ptr noundef) ; Currently this fails decomposition. No reproducer should be generated. define i1 @test_inbounds_precondition(ptr %src, i32 %n, i32 %idx) { ; CHECK-NOT: test_inbounds_precondition entry: %upper = getelementptr inbounds i32, ptr %src, i64 5 %src.idx.4 = getelementptr i32, ptr %src, i64 4 %cmp.upper.4 = icmp ule ptr %src.idx.4, %upper br i1 %cmp.upper.4, label %then, label %else then: ret i1 true else: ret i1 false } define i32 @test_branch(i32 %a) { ; CHECK-LABEL: define i1 @"{{.+}}test_branchrepro"(i32 %a) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp ult i32 %a, 4 ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %c.2 = icmp ugt i32 0, 0 ; CHECK-NEXT: ret i1 %c.2 ; CHECK-NEXT: } ; entry: %c.1 = icmp ult i32 %a, 4 br i1 %c.1, label %then, label %exit then: %c.2 = icmp ugt i32 0, 0 call void @use(i1 %c.2) br label %exit exit: ret i32 0 } define i32 @test_invoke(i32 %a) personality ptr null { ; CHECK-LABEL: define i1 @"{{.+}}test_invokerepro"(i32 %l, i32 %a) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp slt i32 %a, %l ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %c.2 = icmp eq i32 0, 0 ; CHECK-NEXT: ret i1 %c.2 ; CHECK-NEXT:} ; entry: %call = invoke ptr null(i64 0) to label %cont unwind label %lpad cont: %l = load i32, ptr %call, align 4 %c.1 = icmp slt i32 %a, %l br i1 %c.1, label %then, label %exit lpad: %lp = landingpad { ptr, i32 } catch ptr null catch ptr null ret i32 0 then: %c.2 = icmp eq i32 0, 0 call void @use(i1 %c.2) br label %exit exit: ret i32 0 } define <2 x i1> @vector_cmp(<2 x ptr> %vec) { ; CHECK-LABEL: define <2 x i1> @"{{.+}}vector_cmprepro"(<2 x ptr> %vec) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %gep.1 = getelementptr inbounds i32, <2 x ptr> %vec, i64 1 ; CHECK-NEXT: %t.1 = icmp ult <2 x ptr> %vec, %gep.1 ; CHECK-NEXT: ret <2 x i1> %t.1 ; CHECK-NEXT: } ; %gep.1 = getelementptr inbounds i32, <2 x ptr> %vec, i64 1 %t.1 = icmp ult <2 x ptr> %vec, %gep.1 ret <2 x i1> %t.1 } define i1 @shared_operand() { ; CHECK-LABEL: define i1 @"{{.+}}shared_operandrepro"() { ; CHECK-NEXT: entry: ; CHECK-NEXT: %sub = sub i8 0, 0 ; CHECK-NEXT: %sub.2 = sub nuw i8 %sub, 0 ; CHECK-NEXT: %c.5 = icmp ult i8 %sub.2, %sub ; CHECK-NEXT: ret i1 %c.5 ; CHECK-NEXT: } ; entry: %sub = sub i8 0, 0 %sub.2 = sub nuw i8 %sub, 0 %c.5 = icmp ult i8 %sub.2, %sub ret i1 %c.5 } @glob = external global i32 define i1 @load_global() { ; CHECK-LABEL: define i1 @"{{.*}}load_globalrepro"(i32 %l) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %c = icmp ugt i32 %l, %l ; CHECK-NEXT: ret i1 %c ; CHECK-NEXT:} ; entry: %l = load i32, ptr @glob, align 8 %c = icmp ugt i32 %l, %l ret i1 %c } define i1 @test_ptr_null_constant(ptr %a) { ; CHECK-LABEL: define i1 @"{{.+}}test_ptr_null_constantrepro"(ptr %a) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp eq ptr %a, null ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %c.2 = icmp eq ptr %a, null ; CHECK-NEXT: ret i1 %c.2 ; CHECK-NEXT: } ; entry: %c.1 = icmp eq ptr %a, null br i1 %c.1, label %then, label %else then: %c.2 = icmp eq ptr %a, null ret i1 %c.2 else: ret i1 false } define i1 @test_both_signed_and_unsigned_conds_needed_in_reproducer(ptr %src, ptr %lower, ptr %upper, i16 %N) { ; CHECK-LABEL: define i1 @"{{.+}}test_both_signed_and_unsigned_conds_needed_in_reproducerrepro"(i16 %N, ptr %src) { ; CHECK-NEXT: entry: ; CHECK-NEXT: %0 = icmp sge i16 %N, 0 ; CHECK-NEXT: call void @llvm.assume(i1 %0) ; CHECK-NEXT: %src.end = getelementptr inbounds i8, ptr %src, i16 %N ; CHECK-NEXT: %cmp.src.start = icmp ule ptr %src, %src.end ; CHECK-NEXT: ret i1 %cmp.src.start ; CHECK-NEXT: } ; entry: %N.pos = icmp sge i16 %N, 0 br i1 %N.pos, label %then, label %else then: %src.end = getelementptr inbounds i8, ptr %src, i16 %N %cmp.src.start = icmp ule ptr %src, %src.end ret i1 %cmp.src.start else: ret i1 false }