1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test that the strcmp library call simplifier works correctly. 3; RUN: opt < %s -passes=instcombine -S | FileCheck %s --check-prefix=NOBCMP 4; RUN: opt < %s -passes=instcombine -mtriple=unknown-unknown-linux-gnu -S | FileCheck %s --check-prefix=BCMP 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" 7 8@hello = constant [6 x i8] c"hello\00" 9@hell = constant [5 x i8] c"hell\00" 10@bell = constant [5 x i8] c"bell\00" 11@null = constant [1 x i8] zeroinitializer 12 13declare i32 @strcmp(ptr, ptr) 14 15; strcmp("", x) -> -*x 16define i32 @test1(ptr %str2) { 17; CHECK-LABEL: @test1( 18; CHECK: %strcmpload = load i8, ptr %str 19; CHECK: %1 = zext i8 %strcmpload to i32 20; CHECK: %2 = sub nsw i32 0, %1 21; CHECK: ret i32 %2 22; NOBCMP-LABEL: @test1( 23; NOBCMP-NEXT: [[STRCMPLOAD:%.*]] = load i8, ptr [[STR2:%.*]], align 1 24; NOBCMP-NEXT: [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 25; NOBCMP-NEXT: [[TEMP1:%.*]] = sub nsw i32 0, [[TMP1]] 26; NOBCMP-NEXT: ret i32 [[TEMP1]] 27; 28; BCMP-LABEL: @test1( 29; BCMP-NEXT: [[STRCMPLOAD:%.*]] = load i8, ptr [[STR2:%.*]], align 1 30; BCMP-NEXT: [[TMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 31; BCMP-NEXT: [[TEMP1:%.*]] = sub nsw i32 0, [[TMP1]] 32; BCMP-NEXT: ret i32 [[TEMP1]] 33; 34 %temp1 = call i32 @strcmp(ptr @null, ptr %str2) 35 ret i32 %temp1 36 37} 38 39; strcmp(x, "") -> *x 40define i32 @test2(ptr %str1) { 41; CHECK-LABEL: @test2( 42; CHECK: %strcmpload = load i8, ptr %str 43; CHECK: %1 = zext i8 %strcmpload to i32 44; CHECK: ret i32 %1 45; NOBCMP-LABEL: @test2( 46; NOBCMP-NEXT: [[STRCMPLOAD:%.*]] = load i8, ptr [[STR1:%.*]], align 1 47; NOBCMP-NEXT: [[TEMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 48; NOBCMP-NEXT: ret i32 [[TEMP1]] 49; 50; BCMP-LABEL: @test2( 51; BCMP-NEXT: [[STRCMPLOAD:%.*]] = load i8, ptr [[STR1:%.*]], align 1 52; BCMP-NEXT: [[TEMP1:%.*]] = zext i8 [[STRCMPLOAD]] to i32 53; BCMP-NEXT: ret i32 [[TEMP1]] 54; 55 %temp1 = call i32 @strcmp(ptr %str1, ptr @null) 56 ret i32 %temp1 57} 58 59; strcmp(x, y) -> cnst 60define i32 @test3() { 61; CHECK-LABEL: @test3( 62; CHECK: ret i32 -1 63; NOBCMP-LABEL: @test3( 64; NOBCMP-NEXT: ret i32 -1 65; 66; BCMP-LABEL: @test3( 67; BCMP-NEXT: ret i32 -1 68; 69 %temp1 = call i32 @strcmp(ptr @hell, ptr @hello) 70 ret i32 %temp1 71} 72 73define i32 @test4() { 74; CHECK-LABEL: @test4( 75; CHECK: ret i32 1 76; NOBCMP-LABEL: @test4( 77; NOBCMP-NEXT: ret i32 1 78; 79; BCMP-LABEL: @test4( 80; BCMP-NEXT: ret i32 1 81; 82 %temp1 = call i32 @strcmp(ptr @hell, ptr @null) 83 ret i32 %temp1 84} 85 86; strcmp(x, y) -> memcmp(x, y, <known length>) 87; (This transform is rather difficult to trigger in a useful manner) 88define i32 @test5(i1 %b) { 89; CHECK-LABEL: @test5( 90; CHECK: %memcmp = call i32 @memcmp(ptr @hello, ptr %str2, i32 5) 91; CHECK: ret i32 %memcmp 92; NOBCMP-LABEL: @test5( 93; NOBCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], ptr @hell, ptr @bell 94; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr noundef nonnull dereferenceable(5) @hello, ptr noundef nonnull dereferenceable(5) [[STR2]], i32 5) 95; NOBCMP-NEXT: ret i32 [[MEMCMP]] 96; 97; BCMP-LABEL: @test5( 98; BCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], ptr @hell, ptr @bell 99; BCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr noundef nonnull dereferenceable(5) @hello, ptr noundef nonnull dereferenceable(5) [[STR2]], i32 5) 100; BCMP-NEXT: ret i32 [[MEMCMP]] 101; 102 %str2 = select i1 %b, ptr @hell, ptr @bell 103 %temp3 = call i32 @strcmp(ptr @hello, ptr %str2) 104 ret i32 %temp3 105} 106 107; strcmp(x,x) -> 0 108define i32 @test6(ptr %str) { 109; CHECK-LABEL: @test6( 110; CHECK: ret i32 0 111; NOBCMP-LABEL: @test6( 112; NOBCMP-NEXT: ret i32 0 113; 114; BCMP-LABEL: @test6( 115; BCMP-NEXT: ret i32 0 116; 117 %temp1 = call i32 @strcmp(ptr %str, ptr %str) 118 ret i32 %temp1 119} 120 121; strcmp(x, y) == 0 -> bcmp(x, y, <known length>) 122define i1 @test7(i1 %b) { 123; NOBCMP-LABEL: @test7( 124; NOBCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], ptr @hell, ptr @bell 125; NOBCMP-NEXT: [[MEMCMP:%.*]] = call i32 @memcmp(ptr noundef nonnull dereferenceable(5) @hello, ptr noundef nonnull dereferenceable(5) [[STR2]], i32 5) 126; NOBCMP-NEXT: [[RES:%.*]] = icmp eq i32 [[MEMCMP]], 0 127; NOBCMP-NEXT: ret i1 [[RES]] 128; 129; BCMP-LABEL: @test7( 130; BCMP-NEXT: [[STR2:%.*]] = select i1 [[B:%.*]], ptr @hell, ptr @bell 131; BCMP-NEXT: [[BCMP:%.*]] = call i32 @bcmp(ptr noundef nonnull dereferenceable(5) @hello, ptr noundef nonnull dereferenceable(5) [[STR2]], i32 5) 132; BCMP-NEXT: [[RES:%.*]] = icmp eq i32 [[BCMP]], 0 133; BCMP-NEXT: ret i1 [[RES]] 134; 135 136 137 %str2 = select i1 %b, ptr @hell, ptr @bell 138 %temp3 = call i32 @strcmp(ptr @hello, ptr %str2) 139 %res = icmp eq i32 %temp3, 0 140 ret i1 %res 141} 142