; LLVM IR from smwikipedia/EmbeddedAndRTOSSamples :: C2.6 (uart)

; Unoptimized IR (clang -disable-llvm-passes):
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.uart = type { ptr, i32, [128 x i8], i32, i32, i32, i32, [128 x i8], i32, i32, i32, i32, i32 }

@uart = external dso_local global [4 x %struct.uart], align 16

; Function Attrs: nounwind uwtable
define dso_local void @uart_init() #0 {
  %1 = alloca i32, align 4
  %2 = alloca ptr, align 8
  call void @llvm.lifetime.start.p0(i64 4, ptr %1) #2
  call void @llvm.lifetime.start.p0(i64 8, ptr %2) #2
  store i32 0, ptr %1, align 4, !tbaa !5
  br label %3

3:                                                ; preds = %61, %0
  %4 = load i32, ptr %1, align 4, !tbaa !5
  %5 = icmp ult i32 %4, 4
  br i1 %5, label %6, label %64

6:                                                ; preds = %3
  %7 = load i32, ptr %1, align 4, !tbaa !5
  %8 = zext i32 %7 to i64
  %9 = getelementptr inbounds [4 x %struct.uart], ptr @uart, i64 0, i64 %8
  store ptr %9, ptr %2, align 8, !tbaa !9
  %10 = load i32, ptr %1, align 4, !tbaa !5
  %11 = icmp ne i32 %10, 3
  br i1 %11, label %12, label %20

12:                                               ; preds = %6
  %13 = load i32, ptr %1, align 4, !tbaa !5
  %14 = mul i32 %13, 4096
  %15 = add i32 270471168, %14
  %16 = zext i32 %15 to i64
  %17 = inttoptr i64 %16 to ptr
  %18 = load ptr, ptr %2, align 8, !tbaa !9
  %19 = getelementptr inbounds %struct.uart, ptr %18, i32 0, i32 0
  store volatile ptr %17, ptr %19, align 8, !tbaa !11
  br label %23

20:                                               ; preds = %6
  %21 = load ptr, ptr %2, align 8, !tbaa !9
  %22 = getelementptr inbounds %struct.uart, ptr %21, i32 0, i32 0
  store volatile ptr inttoptr (i64 268472320 to ptr), ptr %22, align 8, !tbaa !11
  br label %23

23:                                               ; preds = %20, %12
  %24 = load ptr, ptr %2, align 8, !tbaa !9
  %25 = getelementptr inbounds %struct.uart, ptr %24, i32 0, i32 0
  %26 = load volatile ptr, ptr %25, align 8, !tbaa !11
  %27 = getelementptr inbounds i8, ptr %26, i64 44
  %28 = load i8, ptr %27, align 1, !tbaa !13
  %29 = zext i8 %28 to i32
  %30 = and i32 %29, -17
  %31 = trunc i32 %30 to i8
  store i8 %31, ptr %27, align 1, !tbaa !13
  %32 = load ptr, ptr %2, align 8, !tbaa !9
  %33 = getelementptr inbounds %struct.uart, ptr %32, i32 0, i32 0
  %34 = load volatile ptr, ptr %33, align 8, !tbaa !11
  %35 = getelementptr inbounds i8, ptr %34, i64 56
  %36 = load i8, ptr %35, align 1, !tbaa !13
  %37 = zext i8 %36 to i32
  %38 = or i32 %37, 48
  %39 = trunc i32 %38 to i8
  store i8 %39, ptr %35, align 1, !tbaa !13
  %40 = load i32, ptr %1, align 4, !tbaa !5
  %41 = load ptr, ptr %2, align 8, !tbaa !9
  %42 = getelementptr inbounds %struct.uart, ptr %41, i32 0, i32 1
  store volatile i32 %40, ptr %42, align 8, !tbaa !14
  %43 = load ptr, ptr %2, align 8, !tbaa !9
  %44 = getelementptr inbounds %struct.uart, ptr %43, i32 0, i32 6
  store volatile i32 0, ptr %44, align 8, !tbaa !15
  %45 = load ptr, ptr %2, align 8, !tbaa !9
  %46 = getelementptr inbounds %struct.uart, ptr %45, i32 0, i32 5
  store volatile i32 0, ptr %46, align 4, !tbaa !16
  %47 = load ptr, ptr %2, align 8, !tbaa !9
  %48 = getelementptr inbounds %struct.uart, ptr %47, i32 0, i32 3
  store volatile i32 0, ptr %48, align 4, !tbaa !17
  %49 = load ptr, ptr %2, align 8, !tbaa !9
  %50 = getelementptr inbounds %struct.uart, ptr %49, i32 0, i32 4
  store volatile i32 128, ptr %50, align 8, !tbaa !18
  %51 = load ptr, ptr %2, align 8, !tbaa !9
  %52 = getelementptr inbounds %struct.uart, ptr %51, i32 0, i32 11
  store volatile i32 0, ptr %52, align 8, !tbaa !19
  %53 = load ptr, ptr %2, align 8, !tbaa !9
  %54 = getelementptr inbounds %struct.uart, ptr %53, i32 0, i32 10
  store volatile i32 0, ptr %54, align 4, !tbaa !20
  %55 = load ptr, ptr %2, align 8, !tbaa !9
  %56 = getelementptr inbounds %struct.uart, ptr %55, i32 0, i32 8
  store volatile i32 0, ptr %56, align 4, !tbaa !21
  %57 = load ptr, ptr %2, align 8, !tbaa !9
  %58 = getelementptr inbounds %struct.uart, ptr %57, i32 0, i32 9
  store volatile i32 128, ptr %58, align 8, !tbaa !22
  %59 = load ptr, ptr %2, align 8, !tbaa !9
  %60 = getelementptr inbounds %struct.uart, ptr %59, i32 0, i32 12
  store volatile i32 0, ptr %60, align 4, !tbaa !23
  br label %61

61:                                               ; preds = %23
  %62 = load i32, ptr %1, align 4, !tbaa !5
  %63 = add i32 %62, 1
  store i32 %63, ptr %1, align 4, !tbaa !5
  br label %3, !llvm.loop !24

64:                                               ; preds = %3
  call void @llvm.lifetime.end.p0(i64 8, ptr %2) #2
  call void @llvm.lifetime.end.p0(i64 4, ptr %1) #2
  ret void
}

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #1

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) #1

attributes #0 = { nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #2 = { nounwind }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{!"clang version 19.1.0 (git@github.com:llvm/llvm-project.git a4bf6cd7cfb1a1421ba92bca9d017b49936c55e4)"}
!5 = !{!6, !6, i64 0}
!6 = !{!"int", !7, i64 0}
!7 = !{!"omnipotent char", !8, i64 0}
!8 = !{!"Simple C/C++ TBAA"}
!9 = !{!10, !10, i64 0}
!10 = !{!"any pointer", !7, i64 0}
!11 = !{!12, !10, i64 0}
!12 = !{!"uart", !10, i64 0, !6, i64 8, !7, i64 12, !6, i64 140, !6, i64 144, !6, i64 148, !6, i64 152, !7, i64 156, !6, i64 284, !6, i64 288, !6, i64 292, !6, i64 296, !6, i64 300}
!13 = !{!7, !7, i64 0}
!14 = !{!12, !6, i64 8}
!15 = !{!12, !6, i64 152}
!16 = !{!12, !6, i64 148}
!17 = !{!12, !6, i64 140}
!18 = !{!12, !6, i64 144}
!19 = !{!12, !6, i64 296}
!20 = !{!12, !6, i64 292}
!21 = !{!12, !6, i64 284}
!22 = !{!12, !6, i64 288}
!23 = !{!12, !6, i64 300}
!24 = distinct !{!24, !25}
!25 = !{!"llvm.loop.mustprogress"}


; Optimized IR (opt -passes='default<O3>'):
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

%struct.uart = type { ptr, i32, [128 x i8], i32, i32, i32, i32, [128 x i8], i32, i32, i32, i32, i32 }

@uart = external dso_local global [4 x %struct.uart], align 16

; Function Attrs: nofree norecurse nounwind uwtable
define dso_local void @uart_init() local_unnamed_addr #0 {
  store volatile ptr inttoptr (i64 270471168 to ptr), ptr @uart, align 16, !tbaa !5
  %1 = load volatile ptr, ptr @uart, align 16, !tbaa !5
  %2 = getelementptr inbounds i8, ptr %1, i64 44
  %3 = load i8, ptr %2, align 1, !tbaa !11
  %4 = and i8 %3, -17
  store i8 %4, ptr %2, align 1, !tbaa !11
  %5 = load volatile ptr, ptr @uart, align 16, !tbaa !5
  %6 = getelementptr inbounds i8, ptr %5, i64 56
  %7 = load i8, ptr %6, align 1, !tbaa !11
  %8 = or i8 %7, 48
  store i8 %8, ptr %6, align 1, !tbaa !11
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 8), align 8, !tbaa !12
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 152), align 8, !tbaa !13
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 148), align 4, !tbaa !14
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 140), align 4, !tbaa !15
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 144), align 16, !tbaa !16
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 296), align 8, !tbaa !17
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 292), align 4, !tbaa !18
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 284), align 4, !tbaa !19
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 288), align 16, !tbaa !20
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 300), align 4, !tbaa !21
  store volatile ptr inttoptr (i64 270475264 to ptr), ptr getelementptr inbounds (i8, ptr @uart, i64 304), align 16, !tbaa !5
  %9 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 304), align 16, !tbaa !5
  %10 = getelementptr inbounds i8, ptr %9, i64 44
  %11 = load i8, ptr %10, align 1, !tbaa !11
  %12 = and i8 %11, -17
  store i8 %12, ptr %10, align 1, !tbaa !11
  %13 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 304), align 16, !tbaa !5
  %14 = getelementptr inbounds i8, ptr %13, i64 56
  %15 = load i8, ptr %14, align 1, !tbaa !11
  %16 = or i8 %15, 48
  store i8 %16, ptr %14, align 1, !tbaa !11
  store volatile i32 1, ptr getelementptr inbounds (i8, ptr @uart, i64 312), align 8, !tbaa !12
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 456), align 8, !tbaa !13
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 452), align 4, !tbaa !14
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 444), align 4, !tbaa !15
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 448), align 16, !tbaa !16
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 600), align 8, !tbaa !17
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 596), align 4, !tbaa !18
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 588), align 4, !tbaa !19
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 592), align 16, !tbaa !20
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 604), align 4, !tbaa !21
  store volatile ptr inttoptr (i64 270479360 to ptr), ptr getelementptr inbounds (i8, ptr @uart, i64 608), align 16, !tbaa !5
  %17 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 608), align 16, !tbaa !5
  %18 = getelementptr inbounds i8, ptr %17, i64 44
  %19 = load i8, ptr %18, align 1, !tbaa !11
  %20 = and i8 %19, -17
  store i8 %20, ptr %18, align 1, !tbaa !11
  %21 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 608), align 16, !tbaa !5
  %22 = getelementptr inbounds i8, ptr %21, i64 56
  %23 = load i8, ptr %22, align 1, !tbaa !11
  %24 = or i8 %23, 48
  store i8 %24, ptr %22, align 1, !tbaa !11
  store volatile i32 2, ptr getelementptr inbounds (i8, ptr @uart, i64 616), align 8, !tbaa !12
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 760), align 8, !tbaa !13
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 756), align 4, !tbaa !14
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 748), align 4, !tbaa !15
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 752), align 16, !tbaa !16
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 904), align 8, !tbaa !17
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 900), align 4, !tbaa !18
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 892), align 4, !tbaa !19
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 896), align 16, !tbaa !20
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 908), align 4, !tbaa !21
  store volatile ptr inttoptr (i64 268472320 to ptr), ptr getelementptr inbounds (i8, ptr @uart, i64 912), align 16, !tbaa !5
  %25 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 912), align 16, !tbaa !5
  %26 = getelementptr inbounds i8, ptr %25, i64 44
  %27 = load i8, ptr %26, align 1, !tbaa !11
  %28 = and i8 %27, -17
  store i8 %28, ptr %26, align 1, !tbaa !11
  %29 = load volatile ptr, ptr getelementptr inbounds (i8, ptr @uart, i64 912), align 16, !tbaa !5
  %30 = getelementptr inbounds i8, ptr %29, i64 56
  %31 = load i8, ptr %30, align 1, !tbaa !11
  %32 = or i8 %31, 48
  store i8 %32, ptr %30, align 1, !tbaa !11
  store volatile i32 3, ptr getelementptr inbounds (i8, ptr @uart, i64 920), align 8, !tbaa !12
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1064), align 8, !tbaa !13
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1060), align 4, !tbaa !14
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1052), align 4, !tbaa !15
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 1056), align 16, !tbaa !16
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1208), align 8, !tbaa !17
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1204), align 4, !tbaa !18
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1196), align 4, !tbaa !19
  store volatile i32 128, ptr getelementptr inbounds (i8, ptr @uart, i64 1200), align 16, !tbaa !20
  store volatile i32 0, ptr getelementptr inbounds (i8, ptr @uart, i64 1212), align 4, !tbaa !21
  ret void
}

attributes #0 = { nofree norecurse nounwind uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3}
!llvm.ident = !{!4}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{!"clang version 19.1.0 (git@github.com:llvm/llvm-project.git a4bf6cd7cfb1a1421ba92bca9d017b49936c55e4)"}
!5 = !{!6, !7, i64 0}
!6 = !{!"uart", !7, i64 0, !10, i64 8, !8, i64 12, !10, i64 140, !10, i64 144, !10, i64 148, !10, i64 152, !8, i64 156, !10, i64 284, !10, i64 288, !10, i64 292, !10, i64 296, !10, i64 300}
!7 = !{!"any pointer", !8, i64 0}
!8 = !{!"omnipotent char", !9, i64 0}
!9 = !{!"Simple C/C++ TBAA"}
!10 = !{!"int", !8, i64 0}
!11 = !{!8, !8, i64 0}
!12 = !{!6, !10, i64 8}
!13 = !{!6, !10, i64 152}
!14 = !{!6, !10, i64 148}
!15 = !{!6, !10, i64 140}
!16 = !{!6, !10, i64 144}
!17 = !{!6, !10, i64 296}
!18 = !{!6, !10, i64 292}
!19 = !{!6, !10, i64 284}
!20 = !{!6, !10, i64 288}
!21 = !{!6, !10, i64 300}


; Effective O3 passes: EarlyCSEPass,GVNPass,GlobalOptPass,IPSCCPPass,IndVarSimplifyPass,InferAlignmentPass,InferFunctionAttrsPass,InstCombinePass,JumpThreadingPass,LoopRotatePass,PostOrderFunctionAttrsPass,ReassociatePass,SCCPPass,SROAPass,SimplifyCFGPass