1; Test that the memcmp library call simplifier works correctly. 2; 3; RUN: opt < %s -passes=instcombine -S | FileCheck --check-prefix=CHECK --check-prefix=NOBCMP %s 4; RUN: opt < %s -passes=instcombine -mtriple=x86_64-unknown-linux-gnu -S | FileCheck --check-prefix=CHECK --check-prefix=BCMP %s 5 6target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32:64" 7 8@foo = constant [4 x i8] c"foo\00" 9@hel = constant [4 x i8] c"hel\00" 10@hello_u = constant [8 x i8] c"hello_u\00" 11 12declare i32 @memcmp(ptr, ptr, i32) 13 14; Check memcmp(mem, mem, size) -> 0. 15 16define i32 @test_simplify1(ptr %mem, i32 %size) { 17; CHECK-LABEL: @test_simplify1( 18; CHECK-NEXT: ret i32 0 19; 20 %ret = call i32 @memcmp(ptr %mem, ptr %mem, i32 %size) 21 ret i32 %ret 22} 23 24; Check memcmp(mem1, mem2, 0) -> 0. 25 26define i32 @test_simplify2(ptr %mem1, ptr %mem2) { 27; CHECK-LABEL: @test_simplify2( 28; CHECK-NEXT: ret i32 0 29; 30 %ret = call i32 @memcmp(ptr %mem1, ptr %mem2, i32 0) 31 ret i32 %ret 32} 33 34;; Check memcmp(mem1, mem2, 1) -> *(unsigned char*)mem1 - *(unsigned char*)mem2. 35 36define i32 @test_simplify3(ptr %mem1, ptr %mem2) { 37; CHECK-LABEL: @test_simplify3( 38; CHECK-NEXT: [[LHSC:%.*]] = load i8, ptr %mem1, align 1 39; CHECK-NEXT: [[LHSV:%.*]] = zext i8 [[LHSC]] to i32 40; CHECK-NEXT: [[RHSC:%.*]] = load i8, ptr %mem2, align 1 41; CHECK-NEXT: [[RHSV:%.*]] = zext i8 [[RHSC]] to i32 42; CHECK-NEXT: [[CHARDIFF:%.*]] = sub nsw i32 [[LHSV]], [[RHSV]] 43; CHECK-NEXT: ret i32 [[CHARDIFF]] 44; 45 %ret = call i32 @memcmp(ptr %mem1, ptr %mem2, i32 1) 46 ret i32 %ret 47} 48 49; Check memcmp(mem1, mem2, size) -> cnst, where all arguments are constants. 50 51define i32 @test_simplify4() { 52; CHECK-LABEL: @test_simplify4( 53; CHECK-NEXT: ret i32 0 54; 55 %ret = call i32 @memcmp(ptr @hel, ptr @hello_u, i32 3) 56 ret i32 %ret 57} 58 59define i32 @test_simplify5() { 60; CHECK-LABEL: @test_simplify5( 61; CHECK-NEXT: ret i32 1 62; 63 %ret = call i32 @memcmp(ptr @hel, ptr @foo, i32 3) 64 ret i32 %ret 65} 66 67define i32 @test_simplify6() { 68; CHECK-LABEL: @test_simplify6( 69; CHECK-NEXT: ret i32 -1 70; 71 %ret = call i32 @memcmp(ptr @foo, ptr @hel, i32 3) 72 ret i32 %ret 73} 74 75; Check memcmp(mem1, mem2, 8)==0 -> *(int64_t*)mem1 == *(int64_t*)mem2 76 77define i1 @test_simplify7(i64 %x, i64 %y) { 78; CHECK-LABEL: @test_simplify7( 79; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 %x, %y 80; CHECK-NEXT: ret i1 [[CMP]] 81; 82 %x.addr = alloca i64, align 8 83 %y.addr = alloca i64, align 8 84 store i64 %x, ptr %x.addr, align 8 85 store i64 %y, ptr %y.addr, align 8 86 %call = call i32 @memcmp(ptr %x.addr, ptr %y.addr, i32 8) 87 %cmp = icmp eq i32 %call, 0 88 ret i1 %cmp 89} 90 91; Check memcmp(mem1, mem2, 4)==0 -> *(int32_t*)mem1 == *(int32_t*)mem2 92 93define i1 @test_simplify8(i32 %x, i32 %y) { 94; CHECK-LABEL: @test_simplify8( 95; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 %x, %y 96; CHECK-NEXT: ret i1 [[CMP]] 97; 98 %x.addr = alloca i32, align 4 99 %y.addr = alloca i32, align 4 100 store i32 %x, ptr %x.addr, align 4 101 store i32 %y, ptr %y.addr, align 4 102 %call = call i32 @memcmp(ptr %x.addr, ptr %y.addr, i32 4) 103 %cmp = icmp eq i32 %call, 0 104 ret i1 %cmp 105} 106 107; Check memcmp(mem1, mem2, 2)==0 -> *(int16_t*)mem1 == *(int16_t*)mem2 108 109define i1 @test_simplify9(i16 %x, i16 %y) { 110; CHECK-LABEL: @test_simplify9( 111; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 %x, %y 112; CHECK-NEXT: ret i1 [[CMP]] 113; 114 %x.addr = alloca i16, align 2 115 %y.addr = alloca i16, align 2 116 store i16 %x, ptr %x.addr, align 2 117 store i16 %y, ptr %y.addr, align 2 118 %call = call i32 @memcmp(ptr %x.addr, ptr %y.addr, i32 2) 119 %cmp = icmp eq i32 %call, 0 120 ret i1 %cmp 121} 122 123; Check memcmp(mem1, mem2, size)==0 -> bcmp(mem1, mem2, size)==0 124 125define i1 @test_simplify10(ptr %mem1, ptr %mem2, i32 %size) { 126; NOBCMP-LABEL: @test_simplify10( 127; NOBCMP-NEXT: [[CALL:%.*]] = call i32 @memcmp(ptr %mem1, ptr %mem2, i32 %size) 128; NOBCMP-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 129; NOBCMP-NEXT: ret i1 [[CMP]] 130; 131; BCMP-LABEL: @test_simplify10( 132; BCMP-NEXT: [[CALL:%.*]] = call i32 @bcmp(ptr %mem1, ptr %mem2, i32 %size) 133; BCMP-NEXT: [[CMP:%.*]] = icmp eq i32 [[CALL]], 0 134; BCMP-NEXT: ret i1 [[CMP]] 135; 136 %call = call i32 @memcmp(ptr %mem1, ptr %mem2, i32 %size) 137 %cmp = icmp eq i32 %call, 0 138 ret i1 %cmp 139} 140