#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int volatile uint32_t;

/* Variables and functions */
int /*<<< orphan*/ print_str(char *);
void main(void) {
  *(((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x18))) |=
      (uint32_t)(0x00000001 | 0x00000004);
  *(((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x1C))) |=
      (uint32_t)(0x00020000);
  *(((volatile uint32_t *)(((volatile uint32_t)0x40010800) + 0x00))) =
      0x00004B00;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40010800) + 0x04))) =
      0x44444444;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40010800) + 0x0C))) =
      0x00000000;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40010800) + 0x10))) =
      0x00000000;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40010800) + 0x14))) =
      0x00000000;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40004400) + 0x0C))) =
      0x0000000C;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40004400) + 0x10))) =
      0x00000000;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40004400) + 0x14))) =
      0x00000000;
  *(((volatile uint32_t *)(((volatile uint32_t)0x40004400) + 0x0C))) |= 0x2000;
  print_str("Hello World!\n");
  while (1)
    ;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
mov    $0x40021018,%eax
mov    (%rax),%ecx
or     $0x5,%ecx
mov    $0x40021018,%eax
mov    %ecx,(%rax)
mov    $0x4002101c,%eax
mov    (%rax),%ecx
or     $0x20000,%ecx
mov    $0x4002101c,%eax
mov    %ecx,(%rax)
mov    $0x40010800,%eax
movl   $0x4b00,(%rax)
mov    $0x40010804,%eax
movl   $0x44444444,(%rax)
mov    $0x4001080c,%eax
movl   $0x0,(%rax)
mov    $0x40010810,%eax
movl   $0x0,(%rax)
mov    $0x40010814,%eax
movl   $0x0,(%rax)
mov    $0x4000440c,%eax
movl   $0xc,(%rax)
mov    $0x40004410,%eax
movl   $0x0,(%rax)
mov    $0x40004414,%eax
movl   $0x0,(%rax)
mov    $0x4000440c,%eax
mov    (%rax),%ecx
or     $0x2000,%ecx
mov    $0x4000440c,%eax
mov    %ecx,(%rax)
lea    0xe54(%rip),%rdi
call   1030 <print_str@plt>
jmp    11b1 <main+0xa1>

x86 assembly (clang, -O2):
<main>:
push   %rax
orl    $0x5,0x40021018
05
orl    $0x20000,0x4002101c
movl   $0x4b00,0x40010800
movl   $0x44444444,0x40010804
44 44 44 44
movl   $0x0,0x4001080c
movl   $0x0,0x40010810
movl   $0x0,0x40010814
movl   $0xc,0x4000440c
movl   $0x0,0x40004410
movl   $0x0,0x40004414
orl    $0x2000,0x4000440c
lea    0xe72(%rip),%rdi
call   1030 <print_str@plt>
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
jmp    11a0 <main+0x90>

LLVM IR (-O0):
@.str = [14 x i8] c"Hello World!\0A\00"
define void @main() {
%1 = load volatile i32, i32* inttoptr (i64 1073877016 to i32*)
%2 = or i32 %1, 5
store volatile i32 %2, i32* inttoptr (i64 1073877016 to i32*)
%3 = load volatile i32, i32* inttoptr (i64 1073877020 to i32*)
%4 = or i32 %3, 131072
store volatile i32 %4, i32* inttoptr (i64 1073877020 to i32*)
store volatile i32 19200, i32* inttoptr (i64 1073809408 to i32*)
store volatile i32 1145324612, i32* inttoptr (i64 1073809412 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809420 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809424 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809428 to i32*)
store volatile i32 12, i32* inttoptr (i64 1073759244 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073759248 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073759252 to i32*)
%5 = load volatile i32, i32* inttoptr (i64 1073759244 to i32*)
%6 = or i32 %5, 8192
store volatile i32 %6, i32* inttoptr (i64 1073759244 to i32*)
%7 = call i32 @print_str(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0))
br label %8
8: ; preds = %0, %8
br label %8
}

LLVM IR (-O2):
@.str = [14 x i8] c"Hello World!\0A\00"
define void @main() {
%1 = load volatile i32, i32* inttoptr (i64 1073877016 to i32*)
%2 = or i32 %1, 5
store volatile i32 %2, i32* inttoptr (i64 1073877016 to i32*)
%3 = load volatile i32, i32* inttoptr (i64 1073877020 to i32*)
%4 = or i32 %3, 131072
store volatile i32 %4, i32* inttoptr (i64 1073877020 to i32*)
store volatile i32 19200, i32* inttoptr (i64 1073809408 to i32*)
store volatile i32 1145324612, i32* inttoptr (i64 1073809412 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809420 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809424 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073809428 to i32*)
store volatile i32 12, i32* inttoptr (i64 1073759244 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073759248 to i32*)
store volatile i32 0, i32* inttoptr (i64 1073759252 to i32*)
%5 = load volatile i32, i32* inttoptr (i64 1073759244 to i32*)
%6 = or i32 %5, 8192
store volatile i32 %6, i32* inttoptr (i64 1073759244 to i32*)
%7 = tail call i32 @print_str(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @.str, i64 0, i64 0))
br label %8
8: ; preds = %0, %8
br label %8
}