#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 */

/* Variables and functions */
char last_char(char *);
int /*<<< orphan*/ strcat(char *, char *);
int /*<<< orphan*/ strcpy(char *, char const *);
void add(const char *b1, const char *b2, char *out) {
  if (*b1 != '\0' && *b2 != '\0') {
    char c1[16];
    char c2[16];
    char ob1[16];
    char ob2[16];
    char d[3] = {0, 0, 0};
    char L1, L2;
    strcpy(c1, b1);
    strcpy(c2, b2);
    L1 = last_char(c1);
    L2 = last_char(c2);
    if (L2 < L1) {
      L2 ^= L1;
      L1 ^= L2;
      L2 ^= L1;
    }
    if (L1 == '-') {
      if (L2 == '0') {
        d[0] = '-';
      }
      if (L2 == '-') {
        d[0] = '+';
        d[1] = '-';
      }
    }
    if (L1 == '+') {
      if (L2 == '0') {
        d[0] = '+';
      }
      if (L2 == '-') {
        d[0] = '0';
      }
      if (L2 == '+') {
        d[0] = '-';
        d[1] = '+';
      }
    }
    if (L1 == '0') {
      if (L2 == '0') {
        d[0] = '0';
      }
    }
    add(c1, &d[1], ob1);
    add(ob1, c2, ob2);
    strcpy(out, ob2);
    d[1] = 0;
    strcat(out, d);
  } else if (*b1 != '\0') {
    strcpy(out, b1);
  } else if (*b2 != '\0') {
    strcpy(out, b2);
  } else {
    *out = '\0';
  }
}


x86 assembly (clang, -O0):
<add>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %rdx,-0x18(%rbp)
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     12ea <add+0x19a>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     12ea <add+0x19a>
lea    -0x63(%rbp),%rdi
xor    %esi,%esi
mov    $0x3,%edx
call   1060 <memset@plt>
lea    -0x30(%rbp),%rdi
mov    -0x8(%rbp),%rsi
call   1040 <strcpy@plt>
lea    -0x40(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1040 <strcpy@plt>
lea    -0x30(%rbp),%rdi
call   1050 <last_char@plt>
mov    %al,-0x64(%rbp)
lea    -0x40(%rbp),%rdi
call   1050 <last_char@plt>
mov    %al,-0x65(%rbp)
movsbl -0x65(%rbp),%eax
movsbl -0x64(%rbp),%ecx
cmp    %ecx,%eax
jge    11fd <add+0xad>
movsbl -0x64(%rbp),%ecx
movsbl -0x65(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x65(%rbp)
movsbl -0x65(%rbp),%ecx
movsbl -0x64(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x64(%rbp)
movsbl -0x64(%rbp),%ecx
movsbl -0x65(%rbp),%eax
xor    %ecx,%eax
mov    %al,-0x65(%rbp)
movsbl -0x64(%rbp),%eax
cmp    $0x2d,%eax
jne    1235 <add+0xe5>
movsbl -0x65(%rbp),%eax
cmp    $0x30,%eax
jne    121b <add+0xcb>
movb   $0x2d,-0x63(%rbp)
movsbl -0x65(%rbp),%eax
cmp    $0x2d,%eax
jne    1230 <add+0xe0>
movb   $0x2b,-0x63(%rbp)
movb   $0x2d,-0x62(%rbp)
jmp    1235 <add+0xe5>
movsbl -0x64(%rbp),%eax
cmp    $0x2b,%eax
jne    127e <add+0x12e>
movsbl -0x65(%rbp),%eax
cmp    $0x30,%eax
jne    1253 <add+0x103>
movb   $0x2b,-0x63(%rbp)
movsbl -0x65(%rbp),%eax
cmp    $0x2d,%eax
jne    1264 <add+0x114>
movb   $0x30,-0x63(%rbp)
movsbl -0x65(%rbp),%eax
cmp    $0x2b,%eax
jne    1279 <add+0x129>
movb   $0x2d,-0x63(%rbp)
movb   $0x2b,-0x62(%rbp)
jmp    127e <add+0x12e>
movsbl -0x64(%rbp),%eax
cmp    $0x30,%eax
jne    12a1 <add+0x151>
movsbl -0x65(%rbp),%eax
cmp    $0x30,%eax
jne    129c <add+0x14c>
movb   $0x30,-0x63(%rbp)
jmp    12a1 <add+0x151>
lea    -0x30(%rbp),%rdi
lea    -0x63(%rbp),%rsi
add    $0x1,%rsi
lea    -0x50(%rbp),%rdx
call   1030 <add@plt>
lea    -0x50(%rbp),%rdi
lea    -0x40(%rbp),%rsi
lea    -0x60(%rbp),%rdx
call   1030 <add@plt>
mov    -0x18(%rbp),%rdi
lea    -0x60(%rbp),%rsi
call   1040 <strcpy@plt>
movb   $0x0,-0x62(%rbp)
mov    -0x18(%rbp),%rdi
lea    -0x63(%rbp),%rsi
call   1070 <strcat@plt>
jmp    133f <add+0x1ef>
mov    -0x8(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     130c <add+0x1bc>
mov    -0x18(%rbp),%rdi
mov    -0x8(%rbp),%rsi
call   1040 <strcpy@plt>
jmp    133a <add+0x1ea>
mov    -0x10(%rbp),%rax
movsbl (%rax),%eax
cmp    $0x0,%eax
je     132e <add+0x1de>
mov    -0x18(%rbp),%rdi
mov    -0x10(%rbp),%rsi
call   1040 <strcpy@plt>
jmp    1335 <add+0x1e5>
mov    -0x18(%rbp),%rax
movb   $0x0,(%rax)
jmp    133a <add+0x1ea>
jmp    133f <add+0x1ef>
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<add>:
push   %r15
push   %r14
push   %r12
push   %rbx
sub    $0x58,%rsp
mov    %rdx,%r14
mov    %rsi,%rbx
cmpb   $0x0,(%rdi)
mov    (%rsi),%al
je     11c3 <add+0x83>
mov    %rdi,%rsi
test   %al,%al
je     11cf <add+0x8f>
movb   $0x0,0xe(%rsp)
movw   $0x0,0xc(%rsp)
lea    0x20(%rsp),%r15
mov    %r15,%rdi
call   1040 <strcpy@plt>
lea    0x10(%rsp),%r12
mov    %r12,%rdi
mov    %rbx,%rsi
call   1040 <strcpy@plt>
mov    %r15,%rdi
call   1050 <last_char@plt>
mov    %eax,%ebx
mov    %r12,%rdi
call   1050 <last_char@plt>
cmp    %bl,%al
movzbl %bl,%edx
movzbl %al,%eax
mov    %edx,%ecx
cmovl  %eax,%ecx
cmovl  %edx,%eax
cmp    $0x2b,%cl
je     11e8 <add+0xa8>
cmp    $0x2d,%cl
jne    11fb <add+0xbb>
cmp    $0x2d,%al
je     120b <add+0xcb>
cmp    $0x30,%al
jne    121b <add+0xdb>
movb   $0x2d,0xc(%rsp)
jmp    121b <add+0xdb>
test   %al,%al
je     11e2 <add+0xa2>
mov    %r14,%rdi
mov    %rbx,%rsi
jmp    11d2 <add+0x92>
mov    %r14,%rdi
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
jmp    1040 <strcpy@plt>
movb   $0x0,(%r14)
jmp    1264 <add+0x124>
cmp    $0x2b,%al
je     1214 <add+0xd4>
cmp    $0x2d,%al
je     1204 <add+0xc4>
cmp    $0x30,%al
jne    121b <add+0xdb>
movb   $0x2b,0xc(%rsp)
jmp    121b <add+0xdb>
cmp    $0x30,%cl
jne    121b <add+0xdb>
cmp    $0x30,%al
jne    121b <add+0xdb>
movb   $0x30,0xc(%rsp)
jmp    121b <add+0xdb>
movw   $0x2d2b,0xc(%rsp)
jmp    121b <add+0xdb>
movw   $0x2b2d,0xc(%rsp)
lea    0xd(%rsp),%rsi
lea    0x20(%rsp),%rdi
lea    0x40(%rsp),%r15
mov    %r15,%rdx
call   1030 <add@plt>
lea    0x10(%rsp),%rsi
lea    0x30(%rsp),%rbx
mov    %r15,%rdi
mov    %rbx,%rdx
call   1030 <add@plt>
mov    %r14,%rdi
mov    %rbx,%rsi
call   1040 <strcpy@plt>
movb   $0x0,0xd(%rsp)
lea    0xc(%rsp),%rsi
mov    %r14,%rdi
call   1060 <strcat@plt>
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @add(i8* %0, i8* %1, i8* %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i8*
%7 = alloca [16 x i8]
%8 = alloca [16 x i8]
%9 = alloca [16 x i8]
%10 = alloca [16 x i8]
%11 = alloca [3 x i8]
%12 = alloca i8
%13 = alloca i8
store i8* %0, i8** %4
store i8* %1, i8** %5
store i8* %2, i8** %6
%14 = load i8*, i8** %4
%15 = load i8, i8* %14
%16 = sext i8 %15 to i32
%17 = icmp ne i32 %16, 0
br i1 %17, label %18, label %126
18: ; preds = %3
%19 = load i8*, i8** %5
%20 = load i8, i8* %19
%21 = sext i8 %20 to i32
%22 = icmp ne i32 %21, 0
br i1 %22, label %23, label %126
23: ; preds = %18
%24 = bitcast [3 x i8]* %11 to i8*
%25 = getelementptr inbounds [16 x i8], [16 x i8]* %7, i64 0, i64 0
%26 = load i8*, i8** %4
%27 = call i32 @strcpy(i8* %25, i8* %26)
%28 = getelementptr inbounds [16 x i8], [16 x i8]* %8, i64 0, i64 0
%29 = load i8*, i8** %5
%30 = call i32 @strcpy(i8* %28, i8* %29)
%31 = getelementptr inbounds [16 x i8], [16 x i8]* %7, i64 0, i64 0
%32 = call signext i8 @last_char(i8* %31)
store i8 %32, i8* %12
%33 = getelementptr inbounds [16 x i8], [16 x i8]* %8, i64 0, i64 0
%34 = call signext i8 @last_char(i8* %33)
store i8 %34, i8* %13
%35 = load i8, i8* %13
%36 = sext i8 %35 to i32
%37 = load i8, i8* %12
%38 = sext i8 %37 to i32
%39 = icmp slt i32 %36, %38
br i1 %39, label %40, label %59
40: ; preds = %23
%41 = load i8, i8* %12
%42 = sext i8 %41 to i32
%43 = load i8, i8* %13
%44 = sext i8 %43 to i32
%45 = xor i32 %44, %42
%46 = trunc i32 %45 to i8
store i8 %46, i8* %13
%47 = load i8, i8* %13
%48 = sext i8 %47 to i32
%49 = load i8, i8* %12
%50 = sext i8 %49 to i32
%51 = xor i32 %50, %48
%52 = trunc i32 %51 to i8
store i8 %52, i8* %12
%53 = load i8, i8* %12
%54 = sext i8 %53 to i32
%55 = load i8, i8* %13
%56 = sext i8 %55 to i32
%57 = xor i32 %56, %54
%58 = trunc i32 %57 to i8
store i8 %58, i8* %13
br label %59
59: ; preds = %40, %23
%60 = load i8, i8* %12
%61 = sext i8 %60 to i32
%62 = icmp eq i32 %61, 45
br i1 %62, label %63, label %77
63: ; preds = %59
%64 = load i8, i8* %13
%65 = sext i8 %64 to i32
%66 = icmp eq i32 %65, 48
br i1 %66, label %67, label %69
67: ; preds = %63
%68 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 45, i8* %68
br label %69
69: ; preds = %67, %63
%70 = load i8, i8* %13
%71 = sext i8 %70 to i32
%72 = icmp eq i32 %71, 45
br i1 %72, label %73, label %76
73: ; preds = %69
%74 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 43, i8* %74
%75 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 1
store i8 45, i8* %75
br label %76
76: ; preds = %73, %69
br label %77
77: ; preds = %76, %59
%78 = load i8, i8* %12
%79 = sext i8 %78 to i32
%80 = icmp eq i32 %79, 43
br i1 %80, label %81, label %101
81: ; preds = %77
%82 = load i8, i8* %13
%83 = sext i8 %82 to i32
%84 = icmp eq i32 %83, 48
br i1 %84, label %85, label %87
85: ; preds = %81
%86 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 43, i8* %86
br label %87
87: ; preds = %85, %81
%88 = load i8, i8* %13
%89 = sext i8 %88 to i32
%90 = icmp eq i32 %89, 45
br i1 %90, label %91, label %93
91: ; preds = %87
%92 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 48, i8* %92
br label %93
93: ; preds = %91, %87
%94 = load i8, i8* %13
%95 = sext i8 %94 to i32
%96 = icmp eq i32 %95, 43
br i1 %96, label %97, label %100
97: ; preds = %93
%98 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 45, i8* %98
%99 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 1
store i8 43, i8* %99
br label %100
100: ; preds = %97, %93
br label %101
101: ; preds = %100, %77
%102 = load i8, i8* %12
%103 = sext i8 %102 to i32
%104 = icmp eq i32 %103, 48
br i1 %104, label %105, label %112
105: ; preds = %101
%106 = load i8, i8* %13
%107 = sext i8 %106 to i32
%108 = icmp eq i32 %107, 48
br i1 %108, label %109, label %111
109: ; preds = %105
%110 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
store i8 48, i8* %110
br label %111
111: ; preds = %109, %105
br label %112
112: ; preds = %111, %101
%113 = getelementptr inbounds [16 x i8], [16 x i8]* %7, i64 0, i64 0
%114 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 1
%115 = getelementptr inbounds [16 x i8], [16 x i8]* %9, i64 0, i64 0
%116 = getelementptr inbounds [16 x i8], [16 x i8]* %9, i64 0, i64 0
%117 = getelementptr inbounds [16 x i8], [16 x i8]* %8, i64 0, i64 0
%118 = getelementptr inbounds [16 x i8], [16 x i8]* %10, i64 0, i64 0
%119 = load i8*, i8** %6
%120 = getelementptr inbounds [16 x i8], [16 x i8]* %10, i64 0, i64 0
%121 = call i32 @strcpy(i8* %119, i8* %120)
%122 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 1
store i8 0, i8* %122
%123 = load i8*, i8** %6
%124 = getelementptr inbounds [3 x i8], [3 x i8]* %11, i64 0, i64 0
%125 = call i32 @strcat(i8* %123, i8* %124)
br label %148
126: ; preds = %18, %3
%127 = load i8*, i8** %4
%128 = load i8, i8* %127
%129 = sext i8 %128 to i32
%130 = icmp ne i32 %129, 0
br i1 %130, label %131, label %135
131: ; preds = %126
%132 = load i8*, i8** %6
%133 = load i8*, i8** %4
%134 = call i32 @strcpy(i8* %132, i8* %133)
br label %147
135: ; preds = %126
%136 = load i8*, i8** %5
%137 = load i8, i8* %136
%138 = sext i8 %137 to i32
%139 = icmp ne i32 %138, 0
br i1 %139, label %140, label %144
140: ; preds = %135
%141 = load i8*, i8** %6
%142 = load i8*, i8** %5
%143 = call i32 @strcpy(i8* %141, i8* %142)
br label %146
144: ; preds = %135
%145 = load i8*, i8** %6
store i8 0, i8* %145
br label %146
146: ; preds = %144, %140
br label %147
147: ; preds = %146, %131
br label %148
148: ; preds = %147, %112
ret void
}

LLVM IR (-O2):
define void @add(i8* %0, i8* %1, i8* %2) {
%4 = alloca [16 x i8]
%5 = alloca [16 x i8]
%6 = alloca [16 x i8]
%7 = alloca [16 x i8]
%8 = alloca [3 x i8]
%9 = load i8, i8* %0
%10 = icmp eq i8 %9, 0
%11 = load i8, i8* %1
%12 = icmp eq i8 %11, 0
br i1 %10, label %47, label %13
13: ; preds = %3
br i1 %12, label %45, label %14
14: ; preds = %13
%15 = getelementptr inbounds [16 x i8], [16 x i8]* %4, i64 0, i64 0
%16 = getelementptr inbounds [16 x i8], [16 x i8]* %5, i64 0, i64 0
%17 = getelementptr inbounds [16 x i8], [16 x i8]* %6, i64 0, i64 0
%18 = getelementptr inbounds [16 x i8], [16 x i8]* %7, i64 0, i64 0
%19 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i64 0, i64 0
%20 = call i32 @strcpy(i8* %15, i8* %0)
%21 = call i32 @strcpy(i8* %16, i8* %1)
%22 = call signext i8 @last_char(i8* %15)
%23 = call signext i8 @last_char(i8* %16)
%24 = icmp slt i8 %23, %22
%25 = select i1 %24, i8 %23, i8 %22
%26 = select i1 %24, i8 %22, i8 %23
switch i8 %25, label %36 [
i8 45, label %27
i8 43, label %31
]
27: ; preds = %14
switch i8 %26, label %41 [
i8 48, label %28
i8 45, label %29
]
28: ; preds = %27
store i8 45, i8* %19
br label %41
29: ; preds = %27
store i8 43, i8* %19
%30 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i64 0, i64 1
store i8 45, i8* %30
br label %41
31: ; preds = %14
switch i8 %26, label %41 [
i8 48, label %32
i8 45, label %33
i8 43, label %34
]
32: ; preds = %31
store i8 43, i8* %19
br label %41
33: ; preds = %31
store i8 48, i8* %19
br label %41
34: ; preds = %31
store i8 45, i8* %19
%35 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i64 0, i64 1
store i8 43, i8* %35
br label %41
36: ; preds = %14
%37 = icmp eq i8 %25, 48
%38 = icmp eq i8 %26, 48
%39 = select i1 %37, i1 %38, i1 false
br i1 %39, label %40, label %41
40: ; preds = %36
store i8 48, i8* %19
br label %41
41: ; preds = %34, %31, %32, %33, %28, %27, %29, %40, %36
%42 = getelementptr inbounds [3 x i8], [3 x i8]* %8, i64 0, i64 1
%43 = call i32 @strcpy(i8* %2, i8* %18)
store i8 0, i8* %42
%44 = call i32 @strcat(i8* %2, i8* %19)
br label %51
45: ; preds = %13
%46 = tail call i32 @strcpy(i8* %2, i8* %0)
br label %51
47: ; preds = %3
br i1 %12, label %50, label %48
48: ; preds = %47
%49 = tail call i32 @strcpy(i8* %2, i8* %1)
br label %51
50: ; preds = %47
store i8 0, i8* %2
br label %51
51: ; preds = %45, %50, %48, %41
ret void
}