1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes=aggressive-instcombine < %s | FileCheck %s 3 4; check whether we generate the right IR 5 6declare i32 @strncmp(ptr nocapture, ptr nocapture, i64) 7declare i32 @strcmp(ptr nocapture, ptr nocapture) 8 9@s2 = constant [2 x i8] c"a\00" 10@s3 = constant [3 x i8] c"ab\00" 11@s3ff = constant [3 x i8] c"\FE\FF\00" 12 13define i1 @test_strncmp_1(ptr %s) { 14; CHECK-LABEL: define i1 @test_strncmp_1( 15; CHECK-SAME: ptr [[S:%.*]]) { 16; CHECK-NEXT: entry: 17; CHECK-NEXT: br label [[SUB:%.*]] 18; CHECK: sub_0: 19; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 20; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 21; CHECK-NEXT: [[TMP2:%.*]] = sub i32 97, [[TMP1]] 22; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 23; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 24; CHECK: sub_1: 25; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 26; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 27; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 28; CHECK-NEXT: [[TMP7:%.*]] = sub i32 98, [[TMP6]] 29; CHECK-NEXT: br label [[NE]] 30; CHECK: ne: 31; CHECK-NEXT: [[TMP8:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ] 32; CHECK-NEXT: br label [[ENTRY:%.*]] 33; CHECK: entry.tail: 34; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP8]], 0 35; CHECK-NEXT: ret i1 [[CMP]] 36; 37entry: 38 %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 2) 39 %cmp = icmp eq i32 %call, 0 40 ret i1 %cmp 41} 42 43define i1 @test_strncmp_2(ptr %s) { 44; CHECK-LABEL: define i1 @test_strncmp_2( 45; CHECK-SAME: ptr [[S:%.*]]) { 46; CHECK-NEXT: entry: 47; CHECK-NEXT: br label [[SUB:%.*]] 48; CHECK: sub_0: 49; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 50; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 51; CHECK-NEXT: [[TMP2:%.*]] = sub i32 97, [[TMP1]] 52; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 53; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 54; CHECK: sub_1: 55; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 56; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 57; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 58; CHECK-NEXT: [[TMP7:%.*]] = sub i32 98, [[TMP6]] 59; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0 60; CHECK-NEXT: br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]] 61; CHECK: sub_2: 62; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2 63; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1 64; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 65; CHECK-NEXT: [[TMP12:%.*]] = sub i32 0, [[TMP11]] 66; CHECK-NEXT: br label [[NE]] 67; CHECK: ne: 68; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ] 69; CHECK-NEXT: br label [[ENTRY:%.*]] 70; CHECK: entry.tail: 71; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP13]], 0 72; CHECK-NEXT: ret i1 [[CMP]] 73; 74entry: 75 %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 3) 76 %cmp = icmp slt i32 %call, 0 77 ret i1 %cmp 78} 79 80define i1 @test_strncmp_3(ptr %s) { 81; CHECK-LABEL: define i1 @test_strncmp_3( 82; CHECK-SAME: ptr [[S:%.*]]) { 83; CHECK-NEXT: entry: 84; CHECK-NEXT: br label [[SUB:%.*]] 85; CHECK: sub_0: 86; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 87; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 88; CHECK-NEXT: [[TMP2:%.*]] = sub i32 97, [[TMP1]] 89; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 90; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 91; CHECK: sub_1: 92; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 93; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 94; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 95; CHECK-NEXT: [[TMP7:%.*]] = sub i32 98, [[TMP6]] 96; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0 97; CHECK-NEXT: br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]] 98; CHECK: sub_2: 99; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2 100; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1 101; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 102; CHECK-NEXT: [[TMP12:%.*]] = sub i32 0, [[TMP11]] 103; CHECK-NEXT: br label [[NE]] 104; CHECK: ne: 105; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ] 106; CHECK-NEXT: br label [[ENTRY:%.*]] 107; CHECK: entry.tail: 108; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP13]], 0 109; CHECK-NEXT: ret i1 [[CMP]] 110; 111entry: 112 %call = tail call i32 @strncmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s, i64 4) 113 %cmp = icmp sgt i32 %call, 0 114 ret i1 %cmp 115} 116 117define i1 @test_strcmp_1(ptr %s) { 118; CHECK-LABEL: define i1 @test_strcmp_1( 119; CHECK-SAME: ptr [[S:%.*]]) { 120; CHECK-NEXT: entry: 121; CHECK-NEXT: br label [[SUB:%.*]] 122; CHECK: sub_0: 123; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 124; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 125; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], 97 126; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 127; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 128; CHECK: sub_1: 129; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 130; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 131; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 132; CHECK-NEXT: br label [[NE]] 133; CHECK: ne: 134; CHECK-NEXT: [[TMP7:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP6]], [[SUB1]] ] 135; CHECK-NEXT: br label [[ENTRY:%.*]] 136; CHECK: entry.tail: 137; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[TMP7]], 0 138; CHECK-NEXT: ret i1 [[CMP]] 139; 140entry: 141 %call = tail call i32 @strcmp(ptr nonnull dereferenceable(1) %s, ptr nonnull dereferenceable(2) @s2) 142 %cmp = icmp ne i32 %call, 0 143 ret i1 %cmp 144} 145 146define i1 @test_strcmp_2(ptr %s) { 147; CHECK-LABEL: define i1 @test_strcmp_2( 148; CHECK-SAME: ptr [[S:%.*]]) { 149; CHECK-NEXT: entry: 150; CHECK-NEXT: br label [[SUB:%.*]] 151; CHECK: sub_0: 152; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 153; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 154; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[TMP1]], 97 155; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 156; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 157; CHECK: sub_1: 158; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 159; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 160; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 161; CHECK-NEXT: [[TMP7:%.*]] = sub i32 [[TMP6]], 98 162; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0 163; CHECK-NEXT: br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]] 164; CHECK: sub_2: 165; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2 166; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1 167; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 168; CHECK-NEXT: br label [[NE]] 169; CHECK: ne: 170; CHECK-NEXT: [[TMP12:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP11]], [[SUB2]] ] 171; CHECK-NEXT: br label [[ENTRY:%.*]] 172; CHECK: entry.tail: 173; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[TMP12]], 0 174; CHECK-NEXT: ret i1 [[CMP]] 175; 176entry: 177 %call = tail call i32 @strcmp(ptr nonnull dereferenceable(1) %s, ptr nonnull dereferenceable(3) @s3) 178 %cmp = icmp sge i32 %call, 0 179 ret i1 %cmp 180} 181 182define i1 @test_strcmp_3(ptr %s) { 183; CHECK-LABEL: define i1 @test_strcmp_3( 184; CHECK-SAME: ptr [[S:%.*]]) { 185; CHECK-NEXT: entry: 186; CHECK-NEXT: br label [[SUB:%.*]] 187; CHECK: sub_0: 188; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 189; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 190; CHECK-NEXT: [[TMP2:%.*]] = sub i32 97, [[TMP1]] 191; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 192; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB1:%.*]] 193; CHECK: sub_1: 194; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 195; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 196; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 197; CHECK-NEXT: [[TMP7:%.*]] = sub i32 98, [[TMP6]] 198; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0 199; CHECK-NEXT: br i1 [[TMP8]], label [[NE]], label [[SUB2:%.*]] 200; CHECK: sub_2: 201; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2 202; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1 203; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 204; CHECK-NEXT: [[TMP12:%.*]] = sub i32 0, [[TMP11]] 205; CHECK-NEXT: br label [[NE]] 206; CHECK: ne: 207; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB]] ], [ [[TMP7]], [[SUB1]] ], [ [[TMP12]], [[SUB2]] ] 208; CHECK-NEXT: br label [[ENTRY:%.*]] 209; CHECK: entry.tail: 210; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[TMP13]], 0 211; CHECK-NEXT: ret i1 [[CMP]] 212; 213entry: 214 %call = tail call i32 @strcmp(ptr nonnull dereferenceable(3) @s3, ptr nonnull dereferenceable(1) %s) 215 %cmp = icmp sle i32 %call, 0 216 ret i1 %cmp 217} 218 219define i1 @test_strcmp_4(ptr %s) { 220; CHECK-LABEL: define i1 @test_strcmp_4( 221; CHECK-SAME: ptr [[S:%.*]]) { 222; CHECK-NEXT: entry: 223; CHECK-NEXT: br label [[SUB_0:%.*]] 224; CHECK: sub_0: 225; CHECK-NEXT: [[TMP0:%.*]] = load i8, ptr [[S]], align 1 226; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[TMP0]] to i32 227; CHECK-NEXT: [[TMP2:%.*]] = sub i32 254, [[TMP1]] 228; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 229; CHECK-NEXT: br i1 [[TMP3]], label [[NE:%.*]], label [[SUB_1:%.*]] 230; CHECK: sub_1: 231; CHECK-NEXT: [[TMP4:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 1 232; CHECK-NEXT: [[TMP5:%.*]] = load i8, ptr [[TMP4]], align 1 233; CHECK-NEXT: [[TMP6:%.*]] = zext i8 [[TMP5]] to i32 234; CHECK-NEXT: [[TMP7:%.*]] = sub i32 255, [[TMP6]] 235; CHECK-NEXT: [[TMP8:%.*]] = icmp ne i32 [[TMP7]], 0 236; CHECK-NEXT: br i1 [[TMP8]], label [[NE]], label [[SUB_2:%.*]] 237; CHECK: sub_2: 238; CHECK-NEXT: [[TMP9:%.*]] = getelementptr inbounds i8, ptr [[S]], i64 2 239; CHECK-NEXT: [[TMP10:%.*]] = load i8, ptr [[TMP9]], align 1 240; CHECK-NEXT: [[TMP11:%.*]] = zext i8 [[TMP10]] to i32 241; CHECK-NEXT: [[TMP12:%.*]] = sub i32 0, [[TMP11]] 242; CHECK-NEXT: br label [[NE]] 243; CHECK: ne: 244; CHECK-NEXT: [[TMP13:%.*]] = phi i32 [ [[TMP2]], [[SUB_0]] ], [ [[TMP7]], [[SUB_1]] ], [ [[TMP12]], [[SUB_2]] ] 245; CHECK-NEXT: br label [[ENTRY_TAIL:%.*]] 246; CHECK: entry.tail: 247; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP13]], 0 248; CHECK-NEXT: ret i1 [[CMP]] 249; 250entry: 251 %call = tail call i32 @strcmp(ptr nonnull dereferenceable(3) @s3ff, ptr nonnull dereferenceable(1) %s) 252 %cmp = icmp eq i32 %call, 0 253 ret i1 %cmp 254} 255