llvm/llvm/test/Transforms/ConstraintElimination/reproducer-remarks.ll

; 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: <unknown>: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 ptr %dst.0, %upper
  ret i1 %c
}

define void @test_one_known_fact_true_branch(i8 %start, i8 %high) {
; CHECK: remark: <unknown>: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: <unknown>: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: <unknown>: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: <unknown>: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
}