Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
googlebenchmark-state_assembly_test llvm
; ModuleID = '../test/state_assembly_test.cc'
source_filename = "../test/state_assembly_test.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
%"class.benchmark::State" = type { i64, i64, i64, i8, i8, i8, %"class.std::vector", i64, i64, i64, %"class.std::map", i32, i32, %"class.benchmark::internal::ThreadTimer"*, %"class.benchmark::internal::ThreadManager"* }
%"class.std::vector" = type { %"struct.std::Vector_base" }
%"struct.std::Vector_base" = type { %"struct.std::Vector_base<long, std::allocator<long> >::Vector_impl" }
%"struct.std::Vector_base<long, std::allocator<long> >::Vector_impl" = type { i64*, i64*, i64* }
%"class.std::map" = type { %"class.std::Rb_tree" }
%"class.std::Rb_tree" = type { %"struct.std::Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter>, std::Select1st<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> > >::Rb_tree_impl" }
%"struct.std::Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter>, std::Select1st<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> > >::Rb_tree_impl" = type { %"struct.std::Rb_tree_key_compare", %"struct.std::Rb_tree_header" }
%"struct.std::Rb_tree_key_compare" = type { %"struct.std::less" }
%"struct.std::less" = type { i8 }
%"struct.std::Rb_tree_header" = type { %"struct.std::Rb_tree_node_base", i64 }
%"struct.std::Rb_tree_node_base" = type { i32, %"struct.std::Rb_tree_node_base"*, %"struct.std::Rb_tree_node_base"*, %"struct.std::Rb_tree_node_base"* }
%"class.benchmark::internal::ThreadTimer" = type opaque
%"class.benchmark::internal::ThreadManager" = type opaque
@.str = private unnamed_addr constant [12 x i8] c"cached_ > 0\00", align 1
@.str.1 = private unnamed_addr constant [33 x i8] c"../include/benchmark/benchmark.h\00", align 1
@__PRETTY_FUNCTION__._ZN9benchmark5State13StateIteratorppEv = private unnamed_addr constant [79 x i8] c"benchmark::State::StateIterator &benchmark::State::StateIterator::operator++()\00", align 1
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @GLOBAL__sub_I_state_assembly_test.cc, i8* null }]
declare dso_local i32 @_ZN9benchmark8internal17InitializeStreamsEv() local_unnamed_addr #0
; Function Attrs: uwtable
define dso_local i32 @test_for_auto_loop() local_unnamed_addr #1 {
%1 = alloca i32, align 4
%2 = tail call dereferenceable(152) %"class.benchmark::State"* @GetState()
%3 = bitcast i32* %1 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4
store i32 42, i32* %1, align 4, !tbaa !2
%4 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 5
%5 = load i8, i8* %4, align 2, !tbaa !6, !range !15
%6 = icmp ne i8 %5, 0
%7 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 2
%8 = load i64, i64* %7, align 8
tail call void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"* nonnull %2)
%9 = icmp eq i64 %8, 0
%10 = or i1 %9, %6
br i1 %10, label %20, label %11, !prof !16
11: ; preds = %0
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 42) #4, !srcloc !17
%12 = icmp sgt i64 %8, 0
br i1 %12, label %13, label %21
13: ; preds = %11, %17
%14 = phi i64 [ %15, %17 ], [ %8, %11 ]
%15 = add nsw i64 %14, -1
%16 = icmp eq i64 %15, 0
br i1 %16, label %20, label %17, !prof !16
17: ; preds = %13
%18 = load i32, i32* %1, align 4, !tbaa !2
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 %18) #4, !srcloc !17
%19 = icmp sgt i64 %15, 0
br i1 %19, label %13, label %21
20: ; preds = %13, %0
call void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"* nonnull %2)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4
ret i32 101
21: ; preds = %17, %11
call void @__assert_fail(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @.str, i64 0, i64 0), i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.1, i64 0, i64 0), i32 699, i8* getelementptr inbounds ([79 x i8], [79 x i8]* @__PRETTY_FUNCTION__._ZN9benchmark5State13StateIteratorppEv, i64 0, i64 0)) #5
unreachable
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2
declare dso_local dereferenceable(152) %"class.benchmark::State"* @GetState() local_unnamed_addr #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2
; Function Attrs: uwtable
define dso_local i32 @test_while_loop() local_unnamed_addr #1 {
%1 = alloca i32, align 4
%2 = tail call dereferenceable(152) %"class.benchmark::State"* @GetState()
%3 = bitcast i32* %1 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #4
store i32 42, i32* %1, align 4, !tbaa !2
%4 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 3
%5 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 0
%6 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 5
br label %7
7: ; preds = %19, %0
%8 = load i64, i64* %5, align 8, !tbaa !18
%9 = icmp slt i64 %8, 1
br i1 %9, label %10, label %19, !prof !16
10: ; preds = %7
%11 = load i8, i8* %4, align 8, !tbaa !19, !range !15
%12 = icmp eq i8 %11, 0
br i1 %12, label %13, label %23
13: ; preds = %10
call void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"* nonnull %2)
%14 = load i8, i8* %6, align 2, !tbaa !6, !range !15
%15 = icmp eq i8 %14, 0
br i1 %15, label %16, label %23
16: ; preds = %13
%17 = load i64, i64* %5, align 8, !tbaa !18
%18 = icmp slt i64 %17, 1
br i1 %18, label %23, label %19
19: ; preds = %16, %7
%20 = phi i64 [ %8, %7 ], [ %17, %16 ]
%21 = add nsw i64 %20, -1
store i64 %21, i64* %5, align 8, !tbaa !18
%22 = load i32, i32* %1, align 4, !tbaa !2
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 %22) #4, !srcloc !17
br label %7
23: ; preds = %16, %13, %10
call void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"* nonnull %2)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #4
ret i32 101
}
declare dso_local void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"*) local_unnamed_addr #0
declare dso_local void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"*) local_unnamed_addr #0
; Function Attrs: noreturn nounwind
declare dso_local void @__assert_fail(i8*, i8*, i32, i8*) local_unnamed_addr #3
; Function Attrs: uwtable
define internal void @GLOBAL__sub_I_state_assembly_test.cc() #1 section ".text.startup" {
%1 = tail call i32 @_ZN9benchmark8internal17InitializeStreamsEv()
ret void
}
attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { argmemonly nounwind }
attributes #3 = { noreturn nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #4 = { nounwind }
attributes #5 = { noreturn nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 9.0.0-svn359999-1~exp1+0~20190505200857.2495~1.gbpe5722d (trunk)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"int", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C++ TBAA"}
!6 = !{!7, !9, i64 26}
!7 = !{!"_ZTSN9benchmark5StateE", !8, i64 0, !8, i64 8, !8, i64 16, !9, i64 24, !9, i64 25, !9, i64 26, !10, i64 32, !8, i64 56, !8, i64 64, !8, i64 72, !11, i64 80, !3, i64 128, !3, i64 132, !14, i64 136, !14, i64 144}
!8 = !{!"long", !4, i64 0}
!9 = !{!"bool", !4, i64 0}
!10 = !{!"_ZTSSt6vectorIlSaIlEE"}
!11 = !{!"_ZTSSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEN9benchmark7CounterESt4lessIS5_ESaISt4pairIKS5_S7_EEE", !12, i64 0}
!12 = !{!"_ZTSSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9benchmark7CounterEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE", !13, i64 0}
!13 = !{!"_ZTSNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9benchmark7CounterEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE13_Rb_tree_implISE_Lb1EEE"}
!14 = !{!"any pointer", !4, i64 0}
!15 = !{i8 0, i8 2}
!16 = !{!"branch_weights", i32 1, i32 2000}
!17 = !{i32 24569}
!18 = !{!7, !8, i64 0}
!19 = !{!7, !9, i64 24}
; ModuleID = '../test/state_assembly_test.cc'
source_filename = "../test/state_assembly_test.cc"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
%"class.benchmark::State" = type { i64, i64, i64, i8, i8, i8, %"class.std::vector", i64, i64, i64, %"class.std::map", i32, i32, %"class.benchmark::internal::ThreadTimer"*, %"class.benchmark::internal::ThreadManager"* }
%"class.std::vector" = type { %"struct.std::Vector_base" }
%"struct.std::Vector_base" = type { %"struct.std::Vector_base<long, std::allocator<long> >::Vector_impl" }
%"struct.std::Vector_base<long, std::allocator<long> >::Vector_impl" = type { i64*, i64*, i64* }
%"class.std::map" = type { %"class.std::Rb_tree" }
%"class.std::Rb_tree" = type { %"struct.std::Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter>, std::Select1st<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> > >::Rb_tree_impl" }
%"struct.std::Rb_tree<std::__cxx11::basic_string<char>, std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter>, std::Select1st<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> >, std::less<std::__cxx11::basic_string<char> >, std::allocator<std::pair<const std::__cxx11::basic_string<char>, benchmark::Counter> > >::Rb_tree_impl" = type { %"struct.std::Rb_tree_key_compare", %"struct.std::Rb_tree_header" }
%"struct.std::Rb_tree_key_compare" = type { %"struct.std::less" }
%"struct.std::less" = type { i8 }
%"struct.std::Rb_tree_header" = type { %"struct.std::Rb_tree_node_base", i64 }
%"struct.std::Rb_tree_node_base" = type { i32, %"struct.std::Rb_tree_node_base"*, %"struct.std::Rb_tree_node_base"*, %"struct.std::Rb_tree_node_base"* }
%"class.benchmark::internal::ThreadTimer" = type opaque
%"class.benchmark::internal::ThreadManager" = type opaque
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @GLOBAL__sub_I_state_assembly_test.cc, i8* null }]
declare dso_local i32 @_ZN9benchmark8internal17InitializeStreamsEv() local_unnamed_addr #0
; Function Attrs: uwtable
define dso_local i32 @test_for_auto_loop() local_unnamed_addr #1 {
%1 = alloca i32, align 4
%2 = tail call dereferenceable(152) %"class.benchmark::State"* @GetState()
%3 = bitcast i32* %1 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #3
store i32 42, i32* %1, align 4, !tbaa !2
%4 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 5
%5 = load i8, i8* %4, align 2, !tbaa !6, !range !15
%6 = icmp ne i8 %5, 0
%7 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 2
%8 = load i64, i64* %7, align 8
tail call void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"* nonnull %2)
%9 = icmp eq i64 %8, 0
%10 = or i1 %9, %6
br i1 %10, label %14, label %11, !prof !16
11: ; preds = %0
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 42) #3, !srcloc !17
%12 = add i64 %8, -1
%13 = icmp eq i64 %12, 0
br i1 %13, label %14, label %15, !prof !16
14: ; preds = %15, %11, %0
call void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"* nonnull %2)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #3
ret i32 101
15: ; preds = %11, %15
%16 = phi i64 [ %18, %15 ], [ %12, %11 ]
%17 = load i32, i32* %1, align 4, !tbaa !2
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 %17) #3, !srcloc !17
%18 = add i64 %16, -1
%19 = icmp eq i64 %18, 0
br i1 %19, label %14, label %15, !prof !16
}
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture) #2
declare dso_local dereferenceable(152) %"class.benchmark::State"* @GetState() local_unnamed_addr #0
; Function Attrs: argmemonly nounwind
declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture) #2
; Function Attrs: uwtable
define dso_local i32 @test_while_loop() local_unnamed_addr #1 {
%1 = alloca i32, align 4
%2 = tail call dereferenceable(152) %"class.benchmark::State"* @GetState()
%3 = bitcast i32* %1 to i8*
call void @llvm.lifetime.start.p0i8(i64 4, i8* nonnull %3) #3
store i32 42, i32* %1, align 4, !tbaa !2
%4 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 3
%5 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 0
%6 = getelementptr inbounds %"class.benchmark::State", %"class.benchmark::State"* %2, i64 0, i32 5
br label %7
7: ; preds = %19, %0
%8 = load i64, i64* %5, align 8, !tbaa !18
%9 = icmp eq i64 %8, 0
br i1 %9, label %10, label %19, !prof !16
10: ; preds = %7
%11 = load i8, i8* %4, align 8, !tbaa !19, !range !15
%12 = icmp eq i8 %11, 0
br i1 %12, label %13, label %23
13: ; preds = %10
call void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"* nonnull %2)
%14 = load i8, i8* %6, align 2, !tbaa !6, !range !15
%15 = icmp eq i8 %14, 0
br i1 %15, label %16, label %23
16: ; preds = %13
%17 = load i64, i64* %5, align 8, !tbaa !18
%18 = icmp eq i64 %17, 0
br i1 %18, label %23, label %19
19: ; preds = %16, %7
%20 = phi i64 [ %8, %7 ], [ %17, %16 ]
%21 = add i64 %20, -1
store i64 %21, i64* %5, align 8, !tbaa !18
%22 = load i32, i32* %1, align 4, !tbaa !2
call void asm sideeffect "", "=*r|m,0,~{memory},~{dirflag},~{fpsr},~{flags}"(i32* nonnull %1, i32 %22) #3, !srcloc !17
br label %7
23: ; preds = %16, %13, %10
call void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"* nonnull %2)
call void @llvm.lifetime.end.p0i8(i64 4, i8* nonnull %3) #3
ret i32 101
}
declare dso_local void @_ZN9benchmark5State16StartKeepRunningEv(%"class.benchmark::State"*) local_unnamed_addr #0
declare dso_local void @_ZN9benchmark5State17FinishKeepRunningEv(%"class.benchmark::State"*) local_unnamed_addr #0
; Function Attrs: uwtable
define internal void @GLOBAL__sub_I_state_assembly_test.cc() #1 section ".text.startup" {
%1 = tail call i32 @_ZN9benchmark8internal17InitializeStreamsEv()
ret void
}
attributes #0 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { argmemonly nounwind }
attributes #3 = { nounwind }
!llvm.module.flags = !{!0}
!llvm.ident = !{!1}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 9.0.0-svn359999-1~exp1+0~20190505200857.2495~1.gbpe5722d (trunk)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"int", !4, i64 0}
!4 = !{!"omnipotent char", !5, i64 0}
!5 = !{!"Simple C++ TBAA"}
!6 = !{!7, !9, i64 26}
!7 = !{!"_ZTSN9benchmark5StateE", !8, i64 0, !8, i64 8, !8, i64 16, !9, i64 24, !9, i64 25, !9, i64 26, !10, i64 32, !8, i64 56, !8, i64 64, !8, i64 72, !11, i64 80, !3, i64 128, !3, i64 132, !14, i64 136, !14, i64 144}
!8 = !{!"long", !4, i64 0}
!9 = !{!"bool", !4, i64 0}
!10 = !{!"_ZTSSt6vectorIlSaIlEE"}
!11 = !{!"_ZTSSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEN9benchmark7CounterESt4lessIS5_ESaISt4pairIKS5_S7_EEE", !12, i64 0}
!12 = !{!"_ZTSSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9benchmark7CounterEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE", !13, i64 0}
!13 = !{!"_ZTSNSt8_Rb_treeINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESt4pairIKS5_N9benchmark7CounterEESt10_Select1stISA_ESt4lessIS5_ESaISA_EE13_Rb_tree_implISE_Lb1EEE"}
!14 = !{!"any pointer", !4, i64 0}
!15 = !{i8 0, i8 2}
!16 = !{!"branch_weights", i32 1, i32 2000}
!17 = !{i32 24640}
!18 = !{!7, !8, i64 0}
!19 = !{!7, !9, i64 24}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment