[InstCombine] auto-generate better checks; NFC

Also, move a test next to its sibling to eliminate a file with just one test.

llvm-svn: 299824
This commit is contained in:
Sanjay Patel 2017-04-09 15:44:59 +00:00
parent a9d67cf601
commit c5f963c2e5
4 changed files with 238 additions and 137 deletions

View File

@ -3,238 +3,291 @@
declare double @llvm.fabs.f64(double) nounwind readnone
define i1 @test1(float %x, float %y) nounwind {
; CHECK-LABEL: @test1(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, %y
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext1 = fpext float %x to double
%ext2 = fpext float %y to double
%cmp = fcmp ogt double %ext1, %ext2
ret i1 %cmp
; CHECK-LABEL: @test1(
; CHECK-NEXT: fcmp ogt float %x, %y
}
define i1 @test2(float %a) nounwind {
; CHECK-LABEL: @test2(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %a, 1.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ogt double %ext, 1.000000e+00
ret i1 %cmp
; CHECK-LABEL: @test2(
; CHECK-NEXT: fcmp ogt float %a, 1.0
}
define i1 @test3(float %a) nounwind {
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[EXT:%.*]] = fpext float %a to double
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float.
ret i1 %cmp
; CHECK-LABEL: @test3(
; CHECK-NEXT: fpext float %a to double
}
define i1 @test4(float %a) nounwind {
; CHECK-LABEL: @test4(
; CHECK-NEXT: [[EXT:%.*]] = fpext float %a to double
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %a to double
%cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float.
ret i1 %cmp
; CHECK-LABEL: @test4(
; CHECK-NEXT: fpext float %a to double
}
define i1 @test5(float %a) nounwind {
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float %a, -1.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg = fsub float -0.000000e+00, %a
%cmp = fcmp ogt float %neg, 1.000000e+00
ret i1 %cmp
; CHECK-LABEL: @test5(
; CHECK-NEXT: fcmp olt float %a, -1.0
}
define i1 @test6(float %x, float %y) nounwind {
; CHECK-LABEL: @test6(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, %y
; CHECK-NEXT: ret i1 [[CMP]]
;
%neg1 = fsub float -0.000000e+00, %x
%neg2 = fsub float -0.000000e+00, %y
%cmp = fcmp olt float %neg1, %neg2
ret i1 %cmp
; CHECK-LABEL: @test6(
; CHECK-NEXT: fcmp ogt float %x, %y
}
define i1 @test7(float %x) nounwind readnone ssp noredzone {
; CHECK-LABEL: @test7(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, 0.000000e+00
; CHECK-NEXT: ret i1 [[CMP]]
;
%ext = fpext float %x to ppc_fp128
%cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000
ret i1 %cmp
; CHECK-LABEL: @test7(
; CHECK-NEXT: fcmp ogt float %x, 0.000000e+00
}
define float @test8(float %x) nounwind readnone optsize ssp {
; CHECK-LABEL: @test8(
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float %x, 0.000000e+00
; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float
; CHECK-NEXT: ret float [[CONV2]]
;
%conv = fpext float %x to double
%cmp = fcmp olt double %conv, 0.000000e+00
%conv1 = zext i1 %cmp to i32
%conv2 = sitofp i32 %conv1 to float
ret float %conv2
; Float comparison to zero shouldn't cast to double.
; CHECK-LABEL: @test8(
; CHECK-NEXT: fcmp olt float %x, 0.000000e+00
}
declare double @fabs(double) nounwind readnone
define i32 @test9(double %a) nounwind {
; CHECK-LABEL: @test9(
; CHECK-NEXT: ret i32 0
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp olt double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test9(
; CHECK-NOT: fabs
; CHECK: ret i32 0
}
define i32 @test9_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test9_intrinsic(
; CHECK-NEXT: ret i32 0
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp olt double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test9_intrinsic(
; CHECK-NOT: fabs
; CHECK: ret i32 0
}
define i32 @test10(double %a) nounwind {
; CHECK-LABEL: @test10(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp ole double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test10(
; CHECK-NOT: fabs
; CHECK: fcmp oeq double %a, 0.000000e+00
}
define i32 @test10_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test10_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp ole double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test10_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp oeq double %a, 0.000000e+00
}
define i32 @test11(double %a) nounwind {
; CHECK-LABEL: @test11(
; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp ogt double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test11(
; CHECK-NOT: fabs
; CHECK: fcmp one double %a, 0.000000e+00
}
define i32 @test11_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test11_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp ogt double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test11_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp one double %a, 0.000000e+00
}
define i32 @test12(double %a) nounwind {
; CHECK-LABEL: @test12(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp oge double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test12(
; CHECK-NOT: fabs
; CHECK: fcmp ord double %a, 0.000000e+00
}
define i32 @test12_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test12_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp oge double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test12_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp ord double %a, 0.000000e+00
}
define i32 @test13(double %a) nounwind {
; CHECK-LABEL: @test13(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp une double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test13(
; CHECK-NOT: fabs
; CHECK: fcmp une double %a, 0.000000e+00
}
define i32 @test13_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test13_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp une double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp une double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test13_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp une double %a, 0.000000e+00
}
define i32 @test14(double %a) nounwind {
; CHECK-LABEL: @test14(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp oeq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test14(
; CHECK-NOT: fabs
; CHECK: fcmp oeq double %a, 0.000000e+00
}
define i32 @test14_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test14_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp oeq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test14_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp oeq double %a, 0.000000e+00
}
define i32 @test15(double %a) nounwind {
; CHECK-LABEL: @test15(
; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp one double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test15(
; CHECK-NOT: fabs
; CHECK: fcmp one double %a, 0.000000e+00
}
define i32 @test15_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test15_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp one double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test15_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp one double %a, 0.000000e+00
}
define i32 @test16(double %a) nounwind {
; CHECK-LABEL: @test16(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @fabs(double %a) nounwind
%cmp = fcmp ueq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test16(
; CHECK-NOT: fabs
; CHECK: fcmp ueq double %a, 0.000000e+00
}
define i32 @test16_intrinsic(double %a) nounwind {
; CHECK-LABEL: @test16_intrinsic(
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double %a, 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double @llvm.fabs.f64(double %a) nounwind
%cmp = fcmp ueq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
ret i32 %conv
; CHECK-LABEL: @test16_intrinsic(
; CHECK-NOT: fabs
; CHECK: fcmp ueq double %a, 0.000000e+00
}
; Don't crash.
define i32 @test17(double %a, double (double)* %p) nounwind {
; CHECK-LABEL: @test17(
; CHECK-NEXT: [[CALL:%.*]] = tail call double %p(double %a) #1
; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
; CHECK-NEXT: ret i32 [[CONV]]
;
%call = tail call double %p(double %a) nounwind
%cmp = fcmp ueq double %call, 0.000000e+00
%conv = zext i1 %cmp to i32
@ -243,16 +296,18 @@ define i32 @test17(double %a, double (double)* %p) nounwind {
; Can fold fcmp with undef on one side by choosing NaN for the undef
define i32 @test18_undef_unordered(float %a) nounwind {
; CHECK-LABEL: @test18_undef_unordered
; CHECK: ret i32 1
; CHECK-LABEL: @test18_undef_unordered(
; CHECK-NEXT: ret i32 1
;
%cmp = fcmp ueq float %a, undef
%conv = zext i1 %cmp to i32
ret i32 %conv
}
; Can fold fcmp with undef on one side by choosing NaN for the undef
define i32 @test18_undef_ordered(float %a) nounwind {
; CHECK-LABEL: @test18_undef_ordered
; CHECK: ret i32 0
; CHECK-LABEL: @test18_undef_ordered(
; CHECK-NEXT: ret i32 0
;
%cmp = fcmp oeq float %a, undef
%conv = zext i1 %cmp to i32
ret i32 %conv
@ -264,14 +319,30 @@ define i32 @test18_undef_ordered(float %a) nounwind {
; because whatever you choose for the first undef
; you can choose NaN for the other undef
define i1 @test19_undef_unordered() nounwind {
; CHECK-LABEL: @test19_undef
; CHECK: ret i1 true
; CHECK-LABEL: @test19_undef_unordered(
; CHECK-NEXT: ret i1 true
;
%cmp = fcmp ueq float undef, undef
ret i1 %cmp
}
define i1 @test19_undef_ordered() nounwind {
; CHECK-LABEL: @test19_undef
; CHECK: ret i1 false
; CHECK-LABEL: @test19_undef_ordered(
; CHECK-NEXT: ret i1 false
;
%cmp = fcmp oeq float undef, undef
ret i1 %cmp
}
; PR1570
define i1 @invert_fcmp(float %X, float %Y) {
; CHECK-LABEL: @invert_fcmp(
; CHECK-NEXT: [[TOBOOLNOT5:%.*]] = fcmp uge float %X, %Y
; CHECK-NEXT: ret i1 [[TOBOOLNOT5]]
;
%tmp3 = fcmp olt float %X, %Y
%toBoolnot5 = xor i1 %tmp3, true
ret i1 %toBoolnot5
}

View File

@ -14,67 +14,76 @@ declare i32 @memcmp(i8*, i8*, i32)
define i32 @test_simplify1(i8* %mem, i32 %size) {
; CHECK-LABEL: @test_simplify1(
; CHECK-NEXT: ret i32 0
;
%ret = call i32 @memcmp(i8* %mem, i8* %mem, i32 %size)
ret i32 %ret
; CHECK: ret i32 0
}
; Check memcmp(mem1, mem2, 0) -> 0.
define i32 @test_simplify2(i8* %mem1, i8* %mem2) {
; CHECK-LABEL: @test_simplify2(
; CHECK-NEXT: ret i32 0
;
%ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 0)
ret i32 %ret
; CHECK: ret i32 0
}
;; Check memcmp(mem1, mem2, 1) -> *(unsigned char*)mem1 - *(unsigned char*)mem2.
define i32 @test_simplify3(i8* %mem1, i8* %mem2) {
; CHECK-LABEL: @test_simplify3(
; CHECK-NEXT: [[LHSC:%.*]] = load i8, i8* %mem1, align 1
; CHECK-NEXT: [[LHSV:%.*]] = zext i8 [[LHSC]] to i32
; CHECK-NEXT: [[RHSC:%.*]] = load i8, i8* %mem2, align 1
; CHECK-NEXT: [[RHSV:%.*]] = zext i8 [[RHSC]] to i32
; CHECK-NEXT: [[CHARDIFF:%.*]] = sub nsw i32 [[LHSV]], [[RHSV]]
; CHECK-NEXT: ret i32 [[CHARDIFF]]
;
%ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 1)
; CHECK: [[LOAD1:%[a-z]+]] = load i8, i8* %mem1, align 1
; CHECK: [[ZEXT1:%[a-z]+]] = zext i8 [[LOAD1]] to i32
; CHECK: [[LOAD2:%[a-z]+]] = load i8, i8* %mem2, align 1
; CHECK: [[ZEXT2:%[a-z]+]] = zext i8 [[LOAD2]] to i32
; CHECK: [[RET:%[a-z]+]] = sub nsw i32 [[ZEXT1]], [[ZEXT2]]
ret i32 %ret
; CHECK: ret i32 [[RET]]
}
; Check memcmp(mem1, mem2, size) -> cnst, where all arguments are constants.
define i32 @test_simplify4() {
; CHECK-LABEL: @test_simplify4(
; CHECK-NEXT: ret i32 0
;
%mem1 = getelementptr [4 x i8], [4 x i8]* @hel, i32 0, i32 0
%mem2 = getelementptr [8 x i8], [8 x i8]* @hello_u, i32 0, i32 0
%ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3)
ret i32 %ret
; CHECK: ret i32 0
}
define i32 @test_simplify5() {
; CHECK-LABEL: @test_simplify5(
; CHECK-NEXT: ret i32 1
;
%mem1 = getelementptr [4 x i8], [4 x i8]* @hel, i32 0, i32 0
%mem2 = getelementptr [4 x i8], [4 x i8]* @foo, i32 0, i32 0
%ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3)
ret i32 %ret
; CHECK: ret i32 1
}
define i32 @test_simplify6() {
; CHECK-LABEL: @test_simplify6(
; CHECK-NEXT: ret i32 -1
;
%mem1 = getelementptr [4 x i8], [4 x i8]* @foo, i32 0, i32 0
%mem2 = getelementptr [4 x i8], [4 x i8]* @hel, i32 0, i32 0
%ret = call i32 @memcmp(i8* %mem1, i8* %mem2, i32 3)
ret i32 %ret
; CHECK: ret i32 -1
}
; Check memcmp(mem1, mem2, 8)==0 -> *(int64_t*)mem1 == *(int64_t*)mem2
define i1 @test_simplify7(i64 %x, i64 %y) {
; CHECK-LABEL: @test_simplify7(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 %x, %y
; CHECK-NEXT: ret i1 [[CMP]]
;
%x.addr = alloca i64, align 8
%y.addr = alloca i64, align 8
store i64 %x, i64* %x.addr, align 8
@ -84,14 +93,15 @@ define i1 @test_simplify7(i64 %x, i64 %y) {
%call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 8)
%cmp = icmp eq i32 %call, 0
ret i1 %cmp
; CHECK: %cmp = icmp eq i64 %x, %y
; CHECK: ret i1 %cmp
}
; Check memcmp(mem1, mem2, 4)==0 -> *(int32_t*)mem1 == *(int32_t*)mem2
define i1 @test_simplify8(i32 %x, i32 %y) {
; CHECK-LABEL: @test_simplify8(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %x, %y
; CHECK-NEXT: ret i1 [[CMP]]
;
%x.addr = alloca i32, align 4
%y.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
@ -101,14 +111,15 @@ define i1 @test_simplify8(i32 %x, i32 %y) {
%call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 4)
%cmp = icmp eq i32 %call, 0
ret i1 %cmp
; CHECK: %cmp = icmp eq i32 %x, %y
; CHECK: ret i1 %cmp
}
; Check memcmp(mem1, mem2, 2)==0 -> *(int16_t*)mem1 == *(int16_t*)mem2
define i1 @test_simplify9(i16 %x, i16 %y) {
; CHECK-LABEL: @test_simplify9(
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 %x, %y
; CHECK-NEXT: ret i1 [[CMP]]
;
%x.addr = alloca i16, align 2
%y.addr = alloca i16, align 2
store i16 %x, i16* %x.addr, align 2
@ -118,6 +129,4 @@ define i1 @test_simplify9(i16 %x, i16 %y) {
%call = call i32 @memcmp(i8* %xptr, i8* %yptr, i32 2)
%cmp = icmp eq i32 %call, 0
ret i1 %cmp
; CHECK: %cmp = icmp eq i16 %x, %y
; CHECK: ret i1 %cmp
}

View File

@ -1,13 +0,0 @@
; RUN: opt < %s -instcombine -S | FileCheck %s
; PR1570
define i1 @f(float %X, float %Y) {
entry:
%tmp3 = fcmp olt float %X, %Y ; <i1> [#uses=1]
%toBoolnot5 = xor i1 %tmp3, true ; <i1> [#uses=1]
ret i1 %toBoolnot5
; CHECK-LABEL: @f(
; CHECK-NEXT: entry:
; CHECK-NEXT: %toBoolnot5 = fcmp uge float %X, %Y
; CHECK-NEXT: ret i1 %toBoolnot5
}

View File

@ -1,61 +1,95 @@
; This test makes sure that these instructions are properly eliminated.
;
; RUN: opt < %s -instcombine -S | FileCheck %s
; CHECK-NOT: xor
define i32 @test1(i32 %A) {
%B = xor i32 %A, -1
%C = xor i32 %B, -1
ret i32 %C
; CHECK-LABEL: @test1(
; CHECK-NEXT: ret i32 %A
;
%B = xor i32 %A, -1
%C = xor i32 %B, -1
ret i32 %C
}
define i1 @test2(i32 %A, i32 %B) {
; Can change into setge
%cond = icmp sle i32 %A, %B
%Ret = xor i1 %cond, true
ret i1 %Ret
define i1 @invert_icmp(i32 %A, i32 %B) {
; CHECK-LABEL: @invert_icmp(
; CHECK-NEXT: [[NOT:%.*]] = icmp sgt i32 %A, %B
; CHECK-NEXT: ret i1 [[NOT]]
;
%cmp = icmp sle i32 %A, %B
%not = xor i1 %cmp, true
ret i1 %not
}
; PR1570
define i1 @invert_fcmp(float %X, float %Y) {
; CHECK-LABEL: @invert_fcmp(
; CHECK-NEXT: [[NOT:%.*]] = fcmp uge float %X, %Y
; CHECK-NEXT: ret i1 [[NOT]]
;
%cmp = fcmp olt float %X, %Y
%not = xor i1 %cmp, true
ret i1 %not
}
; Test that De Morgan's law can be instcombined.
define i32 @test3(i32 %A, i32 %B) {
%a = xor i32 %A, -1
%b = xor i32 %B, -1
%c = and i32 %a, %b
%d = xor i32 %c, -1
ret i32 %d
; CHECK-LABEL: @test3(
; CHECK-NEXT: [[C_DEMORGAN:%.*]] = or i32 %A, %B
; CHECK-NEXT: ret i32 [[C_DEMORGAN]]
;
%a = xor i32 %A, -1
%b = xor i32 %B, -1
%c = and i32 %a, %b
%d = xor i32 %c, -1
ret i32 %d
}
; Test that De Morgan's law can work with constants.
define i32 @test4(i32 %A, i32 %B) {
%a = xor i32 %A, -1
%c = and i32 %a, 5
%d = xor i32 %c, -1
ret i32 %d
; CHECK-LABEL: @test4(
; CHECK-NEXT: [[D1:%.*]] = or i32 %A, -6
; CHECK-NEXT: ret i32 [[D1]]
;
%a = xor i32 %A, -1
%c = and i32 %a, 5
%d = xor i32 %c, -1
ret i32 %d
}
; Test the mirror of De Morgan's law.
define i32 @test5(i32 %A, i32 %B) {
%a = xor i32 %A, -1
%b = xor i32 %B, -1
%c = or i32 %a, %b
%d = xor i32 %c, -1
ret i32 %d
; CHECK-LABEL: @test5(
; CHECK-NEXT: [[C_DEMORGAN:%.*]] = and i32 %A, %B
; CHECK-NEXT: ret i32 [[C_DEMORGAN]]
;
%a = xor i32 %A, -1
%b = xor i32 %B, -1
%c = or i32 %a, %b
%d = xor i32 %c, -1
ret i32 %d
}
; PR2298
define zeroext i8 @test6(i32 %a, i32 %b) {
entry:
%tmp1not = xor i32 %a, -1
%tmp2not = xor i32 %b, -1
%tmp3 = icmp slt i32 %tmp1not, %tmp2not
%retval67 = zext i1 %tmp3 to i8
ret i8 %retval67
; CHECK-LABEL: @test6(
; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 %b, %a
; CHECK-NEXT: [[RETVAL67:%.*]] = zext i1 [[TMP3]] to i8
; CHECK-NEXT: ret i8 [[RETVAL67]]
;
%tmp1not = xor i32 %a, -1
%tmp2not = xor i32 %b, -1
%tmp3 = icmp slt i32 %tmp1not, %tmp2not
%retval67 = zext i1 %tmp3 to i8
ret i8 %retval67
}
define <2 x i1> @test7(<2 x i32> %A, <2 x i32> %B) {
%cond = icmp sle <2 x i32> %A, %B
%Ret = xor <2 x i1> %cond, <i1 true, i1 true>
ret <2 x i1> %Ret
; CHECK-LABEL: @test7(
; CHECK-NEXT: [[RET:%.*]] = icmp sgt <2 x i32> %A, %B
; CHECK-NEXT: ret <2 x i1> [[RET]]
;
%cond = icmp sle <2 x i32> %A, %B
%Ret = xor <2 x i1> %cond, <i1 true, i1 true>
ret <2 x i1> %Ret
}