Please use GitHub pull requests for new patches. Phabricator shutdown timeline
Changeset View
Standalone View
test/Transforms/ConstantMerge/initial-match.ll
- This file was added.
; RUN: opt -constmerge -S < %s | FileCheck %s | |||||
hiraditya: Can we reduce the size of this test case and maybe make multiple functions. | |||||
Not Done ReplyInline ActionsI could, but one of the goals is to make sure things work through multiple iterations of the outer while (because an earlier implementation I had didn't). If I break it up then you end up with some single-iteration things. These (if implemented improperly) would break as tested, but wouldn't break in single-iteration. In particular, removeDeadConstantUsers and eraseFromParent are trip hazards because they can invalidate values we discover. For example, you might be tempted to cache initial sequence matches found from one iteration to another (so you don't re-discover them every iteration), but that would break if removeDeadConstantUsers kicks in. jfb: I could, but one of the goals is to make sure things work through multiple iterations of the… | |||||
; Test that constants with similar initial sequence of bytes are merged. | |||||
%foo = type { i16, i8 } | |||||
%baz = type { i16, i8, i8* } | |||||
%bat = type { i16, i8, i8*, i16 } | |||||
; Make sure these are entirely gone: | |||||
; CHECK-NOT: bar_1 | |||||
; CHECK-NOT: bar_2 | |||||
; CHECK-NOT: bar_3 | |||||
; CHECK-NOT: bar_4 | |||||
; CHECK-NOT: bar_5 | |||||
; CHECK-NOT: bar_6 | |||||
; CHECK-NOT: bar_7 | |||||
; CHECK-NOT: bar_8_drop | |||||
; CHECK-NOT: hello_drop | |||||
; CHECK-NOT: hello_drop_me_too | |||||
; CHECK-NOT: arr_2 | |||||
; CHECK-NOT: struct_1 | |||||
; CHECK-NOT: struct_2 | |||||
; CHECK-NOT: vec_2 | |||||
; CHECK-NOT: vec_ptr_1 | |||||
davideUnsubmitted Not Done ReplyInline ActionsCHECK-NOT are really brittle, is there any way you can make this slightly more robust? davide: CHECK-NOT are really brittle, is there any way you can make this slightly more robust? | |||||
; Make sure only these are present: | |||||
; CHECK: @unused = constant | |||||
; CHECK-NEXT: @different = private unnamed_addr constant | |||||
; CHECK-NEXT: @bar_8_keep = private unnamed_addr constant | |||||
; CHECK-NEXT: @helloer = private unnamed_addr constant | |||||
; CHECK-NEXT: @helloworld = private unnamed_addr constant | |||||
; This one is tricky because it contains references to other global constants which should get replaced. | |||||
; CHECK-NEXT: @arr_3 = private unnamed_addr constant [3 x i8*] [{{.*}} @helloworld, {{.*}} @helloer, {{.*}} @helloworld, {{.*}}], align 32 | |||||
; CHECK-NEXT: @struct_3 = private unnamed_addr constant %bat { i16 42, i8 69, i8* getelementptr inbounds ([12 x i8], [12 x i8]* @helloworld, i64 0, i64 0), i16 1337 } | |||||
; CHECK-NEXT: @vec_3 = private unnamed_addr constant <3 x i32> <i32 69, i32 1337, i32 42> | |||||
; CHECK-NEXT: @vec_ptr_2 = private unnamed_addr constant <2 x <2 x i32>*> <<2 x i32>* bitcast (<3 x i32>* @vec_3 to <2 x i32>*), <2 x i32>* bitcast (<3 x i32>* @vec_3 to <2 x i32>*)> | |||||
; CHECK-NEXT: @last = constant i32 1337 | |||||
@unused = constant i32 42 | |||||
@bar_1 = private unnamed_addr constant [1 x %foo] [%foo { i16 257, i8 1 }], align 2 | |||||
@bar_2 = private unnamed_addr constant [2 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 2 | |||||
@different = private unnamed_addr constant [2 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 42 }], align 2 | |||||
@bar_2_electric_boogaloo = private unnamed_addr constant [2 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 2 | |||||
@bar_3 = private unnamed_addr constant [3 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 2 | |||||
@bar_4 = private unnamed_addr constant [4 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@bar_5 = private unnamed_addr constant [5 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@bar_6 = private unnamed_addr constant [6 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@bar_7 = private unnamed_addr constant [7 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@bar_8_drop = private unnamed_addr constant [8 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@bar_8_keep = private unnamed_addr constant [8 x %foo] [%foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }, %foo { i16 257, i8 1 }], align 16 | |||||
@hello_drop = private unnamed_addr constant [5 x i8] c"hello", align 1 | |||||
@hello_drop_me_too = private unnamed_addr constant [5 x i8] c"hello", align 1 | |||||
@helloer = private unnamed_addr constant [7 x i8] c"helloer", align 1 | |||||
@helloworld = private unnamed_addr constant [12 x i8] c"hello world!", align 1 | |||||
@arr_2 = private unnamed_addr constant [2 x i8*] [i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @helloer, i64 0, i64 0)], align 32 | |||||
@arr_3 = private unnamed_addr constant [3 x i8*] [i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop, i64 0, i64 0), i8* getelementptr inbounds ([7 x i8], [7 x i8]* @helloer, i64 0, i64 0), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop_me_too, i64 0, i64 0)], align 16 | |||||
@struct_1 = private unnamed_addr constant %foo { i16 42, i8 69 } | |||||
@struct_2 = private unnamed_addr constant %baz { i16 42, i8 69, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop_me_too, i64 0, i64 0) } | |||||
@struct_3 = private unnamed_addr constant %bat { i16 42, i8 69, i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop, i64 0, i64 0), i16 1337 } | |||||
@vec_2 = private unnamed_addr constant <2 x i32> <i32 69, i32 1337> | |||||
@vec_3 = private unnamed_addr constant <3 x i32> <i32 69, i32 1337, i32 42> | |||||
@vec_ptr_1 = private unnamed_addr constant <1 x <2 x i32>*> <<2 x i32>* @vec_2> | |||||
@vec_ptr_2 = private unnamed_addr constant <2 x <2 x i32>*> <<2 x i32>* @vec_2, <2 x i32>* @vec_2> | |||||
; FIXME: test that two zeroinitializer things get common initial sequence deduplication. Ditto undef. | |||||
@last = constant i32 1337 | |||||
Not Done ReplyInline ActionsI'll look into this soon :) jfb: I'll look into this soon :) | |||||
declare void @usefoo(%foo*) | |||||
declare void @usebaz(%baz*) | |||||
declare void @usebat(%bat*) | |||||
declare void @usefoo1([1 x %foo]*) | |||||
declare void @usefoo2([2 x %foo]*) | |||||
declare void @usefoo3([3 x %foo]*) | |||||
declare void @usefoo4([4 x %foo]*) | |||||
declare void @usefoo5([5 x %foo]*) | |||||
declare void @usefoo6([6 x %foo]*) | |||||
declare void @usefoo7([7 x %foo]*) | |||||
declare void @usefoo8([8 x %foo]*) | |||||
declare void @usei8(i8*) | |||||
declare void @usei8_5([5 x i8]*) | |||||
declare void @usei8_7([7 x i8]*) | |||||
declare void @usei8_12([12 x i8]*) | |||||
declare void @usearr2([2 x i8*]*) | |||||
declare void @usearr3([3 x i8*]*) | |||||
declare void @usevec2(<2 x i32>*) | |||||
declare void @usevec3(<3 x i32>*) | |||||
declare void @usevecptr1(<1 x <2 x i32>*>*) | |||||
declare void @usevecptr2(<2 x <2 x i32>*>*) | |||||
define i32 @main() { ; CHECK-LABEL: @main() | |||||
entry: ; CHECK-LABEL: entry | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([1 x %foo], [1 x %foo]* @bar_1, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([2 x %foo], [2 x %foo]* @bar_2, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([2 x %foo], [2 x %foo]* @different, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@different, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([2 x %foo], [2 x %foo]* @bar_2_electric_boogaloo, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([3 x %foo], [3 x %foo]* @bar_3, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([4 x %foo], [4 x %foo]* @bar_4, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([5 x %foo], [5 x %foo]* @bar_5, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([6 x %foo], [6 x %foo]* @bar_6, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([7 x %foo], [7 x %foo]* @bar_7, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([8 x %foo], [8 x %foo]* @bar_8_drop, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo(%foo* getelementptr inbounds ([8 x %foo], [8 x %foo]* @bar_8_keep, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usefoo({{.*}}@bar_8_keep, i64 0, i64 0)) | |||||
tail call void @usefoo1([1 x %foo]* @bar_1) ; CHECK-NEXT: tail call void @usefoo1({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo2([2 x %foo]* @bar_2) ; CHECK-NEXT: tail call void @usefoo2({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo2([2 x %foo]* @different) ; CHECK-NEXT: tail call void @usefoo2([2 x %foo]* @different) | |||||
tail call void @usefoo2([2 x %foo]* @bar_2_electric_boogaloo) ; CHECK-NEXT: tail call void @usefoo2({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo3([3 x %foo]* @bar_3) ; CHECK-NEXT: tail call void @usefoo3({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo4([4 x %foo]* @bar_4) ; CHECK-NEXT: tail call void @usefoo4({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo5([5 x %foo]* @bar_5) ; CHECK-NEXT: tail call void @usefoo5({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo6([6 x %foo]* @bar_6) ; CHECK-NEXT: tail call void @usefoo6({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo7([7 x %foo]* @bar_7) ; CHECK-NEXT: tail call void @usefoo7({{.*}} bitcast {{.*}}@bar_8_keep | |||||
tail call void @usefoo8([8 x %foo]* @bar_8_drop) ; CHECK-NEXT: tail call void @usefoo8([8 x %foo]* @bar_8_keep) | |||||
tail call void @usefoo8([8 x %foo]* @bar_8_keep) ; CHECK-NEXT: tail call void @usefoo8([8 x %foo]* @bar_8_keep) | |||||
tail call void @usei8(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @hello_drop, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usei8({{.*}}@helloworld, i64 0, i64 0)) | |||||
tail call void @usei8(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @helloer, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usei8({{.*}}@helloer, i64 0, i64 0)) | |||||
tail call void @usei8(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @helloworld, i64 0, i64 0)) ; CHECK-NEXT: tail call void @usei8({{.*}}@helloworld, i64 0, i64 0)) | |||||
tail call void @usei8_5([5 x i8]* @hello_drop) ; CHECK-NEXT: tail call void @usei8_5({{.*}} bitcast {{.*}}@helloworld | |||||
tail call void @usei8_7([7 x i8]* @helloer) ; CHECK-NEXT: tail call void @usei8_7([7 x i8]* @helloer) | |||||
tail call void @usei8_12([12 x i8]* @helloworld) ; CHECK-NEXT: tail call void @usei8_12([12 x i8]* @helloworld) | |||||
tail call void @usearr2([2 x i8*]* @arr_2) ; CHECK-NEXT: tail call void @usearr2([2 x i8*]* bitcast ([3 x i8*]* @arr_3 to [2 x i8*]*)) | |||||
tail call void @usearr3([3 x i8*]* @arr_3) ; CHECK-NEXT: tail call void @usearr3([3 x i8*]* @arr_3) | |||||
tail call void @usefoo(%foo* @struct_1) ; CHECK-NEXT: tail call void @usefoo(%foo* bitcast (%bat* @struct_3 to %foo*)) | |||||
tail call void @usebaz(%baz* @struct_2) ; CHECK-NEXT: tail call void @usebaz(%baz* bitcast (%bat* @struct_3 to %baz*)) | |||||
tail call void @usebat(%bat* @struct_3) ; CHECK-NEXT: tail call void @usebat(%bat* @struct_3) | |||||
tail call void @usevec2(<2 x i32>* @vec_2) ; CHECK-NEXT: tail call void @usevec2(<2 x i32>* bitcast (<3 x i32>* @vec_3 to <2 x i32>*)) | |||||
tail call void @usevec3(<3 x i32>* @vec_3) ; CHECK-NEXT: tail call void @usevec3(<3 x i32>* @vec_3) | |||||
tail call void @usevecptr1(<1 x <2 x i32>*>* @vec_ptr_1) ; CHECK-NEXT: tail call void @usevecptr1(<1 x <2 x i32>*>* bitcast (<2 x <2 x i32>*>* @vec_ptr_2 to <1 x <2 x i32>*>*)) | |||||
tail call void @usevecptr2(<2 x <2 x i32>*>* @vec_ptr_2) ; CHECK-NEXT: tail call void @usevecptr2(<2 x <2 x i32>*>* @vec_ptr_2) | |||||
ret i32 0 | |||||
} |
Can we reduce the size of this test case and maybe make multiple functions.