blob: 6d1348de68354bbeab8c1509df579297a6d8e9aa [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; Verify that strncmp calls with members of constant structs are folded.
;
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
; struct A { char a[3], b[4], c[4]; };
%struct.A = type { [3 x i8], [4 x i8], [4 x i8] }
@a = constant %struct.A { [3 x i8] c"123", [4 x i8] c"1231", [4 x i8] c"2345" }
declare i32 @strncmp(i8*, i8*, i64)
define void @fold_strncmp_Aa_b(i32* %pcmp) {
; CHECK-LABEL: @fold_strncmp_Aa_b(
; CHECK-NEXT: store i32 0, i32* [[PCMP:%.*]], align 4
; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
; CHECK-NEXT: store i32 0, i32* [[PCMP1]], align 4
; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
; CHECK-NEXT: store i32 0, i32* [[PCMP2]], align 4
; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
; CHECK-NEXT: store i32 0, i32* [[PCMP3]], align 4
; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
; CHECK-NEXT: store i32 0, i32* [[PCMP4]], align 4
; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
; CHECK-NEXT: store i32 0, i32* [[PCMP5]], align 4
; CHECK-NEXT: [[PCMP6:%.*]] = getelementptr i32, i32* [[PCMP]], i64 6
; CHECK-NEXT: store i32 0, i32* [[PCMP6]], align 4
; CHECK-NEXT: [[PCMP7:%.*]] = getelementptr i32, i32* [[PCMP]], i64 7
; CHECK-NEXT: store i32 -1, i32* [[PCMP7]], align 4
; CHECK-NEXT: [[PCMP8:%.*]] = getelementptr i32, i32* [[PCMP]], i64 8
; CHECK-NEXT: store i32 -1, i32* [[PCMP8]], align 4
; CHECK-NEXT: [[PCMP9:%.*]] = getelementptr i32, i32* [[PCMP]], i64 9
; CHECK-NEXT: store i32 -1, i32* [[PCMP9]], align 4
; CHECK-NEXT: ret void
;
; p1 = a.a
%p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0
; p2 = a.b
%p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 0
; Fold strncmp(a.a = "123", a.b = "1231", 0) to 0.
%cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0)
%pcmp0 = getelementptr i32, i32* %pcmp, i64 0
store i32 %cmp0, i32* %pcmp0
; Fold strncmp(a.a = "123", a.b = "1231", 1) to 0.
%cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1)
%pcmp1 = getelementptr i32, i32* %pcmp, i64 1
store i32 %cmp1, i32* %pcmp1
; Fold strncmp(a.a = "123", a.b = "1231", 2) to 0.
%cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2)
%pcmp2 = getelementptr i32, i32* %pcmp, i64 2
store i32 %cmp2, i32* %pcmp2
; Fold strncmp(a.a = "123", a.b = "1231", 3) to 0.
%cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3)
%pcmp3 = getelementptr i32, i32* %pcmp, i64 3
store i32 %cmp3, i32* %pcmp3
; Fold strncmp(a.a = "123", a.b = "1231", 4) to 0.
; In this and the subsequent tests, reading past the end of a.a is
; strictly undefined in C/C++ (because it forms a pointer to a distinct
; subobject) but handling such cases as if they were well-defined is
; simpler than trying to exclude them.
%cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4)
%pcmp4 = getelementptr i32, i32* %pcmp, i64 4
store i32 %cmp4, i32* %pcmp4
; Fold strncmp("123", "1231" "2", 5) to 0.
%cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5)
%pcmp5 = getelementptr i32, i32* %pcmp, i64 5
store i32 %cmp5, i32* %pcmp5
; Fold strncmp("123", "1231" "23", 6) to 0.
%cmp6 = call i32 @strncmp(i8* %p1, i8* %p2, i64 6)
%pcmp6 = getelementptr i32, i32* %pcmp, i64 6
store i32 %cmp6, i32* %pcmp6
; Fold strncmp("123", "1231" "2345", 7) to 1.
%cmp7 = call i32 @strncmp(i8* %p1, i8* %p2, i64 7)
%pcmp7 = getelementptr i32, i32* %pcmp, i64 7
store i32 %cmp7, i32* %pcmp7
; Fold strncmp("123", "1231" "2345", 8) to 1.
%cmp8 = call i32 @strncmp(i8* %p1, i8* %p2, i64 8)
%pcmp8 = getelementptr i32, i32* %pcmp, i64 8
store i32 %cmp8, i32* %pcmp8
; Fold strncmp("123", "1231" "2345", 9) to 1.
%cmp9 = call i32 @strncmp(i8* %p1, i8* %p2, i64 9)
%pcmp9 = getelementptr i32, i32* %pcmp, i64 9
store i32 %cmp9, i32* %pcmp9
ret void
}
define void @fold_strncmp_Ab_a(i32* %pcmp) {
; CHECK-LABEL: @fold_strncmp_Ab_a(
; CHECK-NEXT: store i32 0, i32* [[PCMP:%.*]], align 4
; CHECK-NEXT: [[PCMP1:%.*]] = getelementptr i32, i32* [[PCMP]], i64 1
; CHECK-NEXT: store i32 0, i32* [[PCMP1]], align 4
; CHECK-NEXT: [[PCMP2:%.*]] = getelementptr i32, i32* [[PCMP]], i64 2
; CHECK-NEXT: store i32 0, i32* [[PCMP2]], align 4
; CHECK-NEXT: [[PCMP3:%.*]] = getelementptr i32, i32* [[PCMP]], i64 3
; CHECK-NEXT: store i32 0, i32* [[PCMP3]], align 4
; CHECK-NEXT: [[PCMP4:%.*]] = getelementptr i32, i32* [[PCMP]], i64 4
; CHECK-NEXT: store i32 1, i32* [[PCMP4]], align 4
; CHECK-NEXT: [[PCMP5:%.*]] = getelementptr i32, i32* [[PCMP]], i64 5
; CHECK-NEXT: store i32 1, i32* [[PCMP5]], align 4
; CHECK-NEXT: ret void
;
; p1 = &a.b[3]
%p1 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 1, i32 3
; p2 = &a.a
%p2 = getelementptr %struct.A, %struct.A* @a, i32 0, i32 0, i32 0
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 0) to 0.
%cmp0 = call i32 @strncmp(i8* %p1, i8* %p2, i64 0)
%pcmp0 = getelementptr i32, i32* %pcmp, i64 0
store i32 %cmp0, i32* %pcmp0
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 1) to 0.
%cmp1 = call i32 @strncmp(i8* %p1, i8* %p2, i64 1)
%pcmp1 = getelementptr i32, i32* %pcmp, i64 1
store i32 %cmp1, i32* %pcmp1
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 2) to 0.
%cmp2 = call i32 @strncmp(i8* %p1, i8* %p2, i64 2)
%pcmp2 = getelementptr i32, i32* %pcmp, i64 2
store i32 %cmp2, i32* %pcmp2
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 3) to 0.
%cmp3 = call i32 @strncmp(i8* %p1, i8* %p2, i64 3)
%pcmp3 = getelementptr i32, i32* %pcmp, i64 3
store i32 %cmp3, i32* %pcmp3
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 4) to 1.
%cmp4 = call i32 @strncmp(i8* %p1, i8* %p2, i64 4)
%pcmp4 = getelementptr i32, i32* %pcmp, i64 4
store i32 %cmp4, i32* %pcmp4
; Fold strncmp(a.a = "123", &a.b[3] = "1" "2345", 5) to 1.
%cmp5 = call i32 @strncmp(i8* %p1, i8* %p2, i64 5)
%pcmp5 = getelementptr i32, i32* %pcmp, i64 5
store i32 %cmp5, i32* %pcmp5
ret void
}