; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -instcombine -S | FileCheck %s
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

define i32 @test_sink_replacement1(i8* %p) {
; CHECK-LABEL: @test_sink_replacement1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i8* [[P:%.*]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i8* [[P]], null
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[CLEANUP:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CALL:%.*]] = call i64 @func_test(i8* nonnull [[P]]) #2
; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[CALL]] to i32
; CHECK-NEXT:    br label [[CLEANUP]]
; CHECK:       cleanup:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_END]] ], [ -1, [[IF_THEN]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %call = call i64 @func_test(i8* nonnull %p) #2
  %conv = trunc i64 %call to i32
  %tobool = icmp ne i8* %p, null
  br i1 %tobool, label %if.end, label %if.then

if.then:
  br label %cleanup

if.end:
  br label %cleanup

cleanup:
  %retval.0 = phi i32 [ %conv, %if.end ], [ -1, %if.then ]
  ret i32 %retval.0
}

define i32 @test_sink_replacement2(i8* %p) {
; CHECK-LABEL: @test_sink_replacement2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i8* [[P:%.*]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i8* [[P]], null
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[CLEANUP:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CALL:%.*]] = call i64 @func_test(i8* nonnull dereferenceable(1) [[P]]) #2
; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[CALL]] to i32
; CHECK-NEXT:    br label [[CLEANUP]]
; CHECK:       cleanup:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_END]] ], [ -1, [[IF_THEN]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %call = call i64 @func_test(i8* dereferenceable(1) %p) #2
  %conv = trunc i64 %call to i32
  %tobool = icmp ne i8* %p, null
  br i1 %tobool, label %if.end, label %if.then

if.then:
  br label %cleanup

if.end:
  br label %cleanup

cleanup:
  %retval.0 = phi i32 [ %conv, %if.end ], [ -1, %if.then ]
  ret i32 %retval.0
}

define i32 @test_sink_replacement3(i8* %p) {
; CHECK-LABEL: @test_sink_replacement3(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i8* [[P:%.*]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i8* [[P]], null
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[CLEANUP:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CALL:%.*]] = call i64 @func_test_nonnull(i8* [[P]]) #2
; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[CALL]] to i32
; CHECK-NEXT:    br label [[CLEANUP]]
; CHECK:       cleanup:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_END]] ], [ -1, [[IF_THEN]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %call = call i64 @func_test_nonnull(i8* %p) #2
  %conv = trunc i64 %call to i32
  %tobool = icmp ne i8* %p, null
  br i1 %tobool, label %if.end, label %if.then

if.then:
  br label %cleanup

if.end:
  br label %cleanup

cleanup:
  %retval.0 = phi i32 [ %conv, %if.end ], [ -1, %if.then ]
  ret i32 %retval.0
}

define i32 @test_sink_replacement4(i8* %p) {
; CHECK-LABEL: @test_sink_replacement4(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    br label [[A:%.*]]
; CHECK:       a:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i8* [[P:%.*]], null
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i8* [[P]], null
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[CLEANUP:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CALL:%.*]] = call i64 @func_test(i8* nonnull dereferenceable(1) [[P]]) #2
; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[CALL]] to i32
; CHECK-NEXT:    br label [[CLEANUP]]
; CHECK:       cleanup:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_END]] ], [ -1, [[IF_THEN]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  br label %a
a:
  %call = call i64 @func_test(i8* dereferenceable(1) %p) #2
  %conv = trunc i64 %call to i32
  %tobool = icmp ne i8* %p, null
  br i1 %tobool, label %if.end, label %if.then

if.then:
  br label %cleanup

if.end:
  br label %cleanup

cleanup:
  %retval.0 = phi i32 [ %conv, %if.end ], [ -1, %if.then ]
  ret i32 %retval.0
}

define i32 @test_sink_replacement5(i64 %i) {
; CHECK-LABEL: @test_sink_replacement5(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[P:%.*]] = inttoptr i64 [[I:%.*]] to i8*
; CHECK-NEXT:    br label [[A:%.*]]
; CHECK:       a:
; CHECK-NEXT:    [[TMP0:%.*]] = icmp ne i64 [[I]], 0
; CHECK-NEXT:    call void @llvm.assume(i1 [[TMP0]])
; CHECK-NEXT:    [[TOBOOL:%.*]] = icmp eq i64 [[I]], 0
; CHECK-NEXT:    br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
; CHECK:       if.then:
; CHECK-NEXT:    br label [[CLEANUP:%.*]]
; CHECK:       if.end:
; CHECK-NEXT:    [[CALL:%.*]] = call i64 @func_test(i8* nonnull dereferenceable(1) [[P]]) #2
; CHECK-NEXT:    [[CONV:%.*]] = trunc i64 [[CALL]] to i32
; CHECK-NEXT:    br label [[CLEANUP]]
; CHECK:       cleanup:
; CHECK-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CONV]], [[IF_END]] ], [ -1, [[IF_THEN]] ]
; CHECK-NEXT:    ret i32 [[RETVAL_0]]
;
entry:
  %p = inttoptr i64 %i to i8*
  br label %a
a:
  %call = call i64 @func_test(i8* dereferenceable(1) %p) #2
  %conv = trunc i64 %call to i32
  %tobool = icmp ne i8* %p, null
  br i1 %tobool, label %if.end, label %if.then

if.then:
  br label %cleanup

if.end:
  br label %cleanup

cleanup:
  %retval.0 = phi i32 [ %conv, %if.end ], [ -1, %if.then ]
  ret i32 %retval.0
}

declare i64 @func_test(i8* %0) #1

declare i64 @func_test_nonnull(i8* nonnull %0) #3

attributes #1 = { readonly }
attributes #2 = { nounwind }
attributes #3 = { readonly }
