#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 */
scalar_t__ islower(char);
scalar_t__ isupper(char);
char rotate(char c) {
  if (islower(c)) {
    return ('a' + (c - 'a' + 3) % 26);
  } else if (isupper(c)) {
    return ('A' + (c - 'A' + 3) % 26);
  } else {
    return c;
  }
}


x86 assembly (clang, -O0):
<rotate>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %dil,%al
mov    %al,-0x2(%rbp)
movsbl -0x2(%rbp),%edi
call   1030 <islower@plt>
cmp    $0x0,%rax
je     1160 <rotate+0x40>
movsbl -0x2(%rbp),%eax
sub    $0x61,%eax
add    $0x3,%eax
mov    $0x1a,%ecx
cltd
idiv   %ecx
add    $0x61,%edx
mov    %dl,%al
mov    %al,-0x1(%rbp)
jmp    1198 <rotate+0x78>
movsbl -0x2(%rbp),%edi
call   1040 <isupper@plt>
cmp    $0x0,%rax
je     1192 <rotate+0x72>
movsbl -0x2(%rbp),%eax
sub    $0x41,%eax
add    $0x3,%eax
mov    $0x1a,%ecx
cltd
idiv   %ecx
add    $0x41,%edx
mov    %dl,%al
mov    %al,-0x1(%rbp)
jmp    1198 <rotate+0x78>
mov    -0x2(%rbp),%al
mov    %al,-0x1(%rbp)
movsbl -0x1(%rbp),%eax
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<rotate>:
push   %rbp
push   %rbx
push   %rax
mov    %edi,%ebx
call   1030 <islower@plt>
test   %rax,%rax
je     1154 <rotate+0x34>
movsbl %bl,%ebx
add    $0xffffffa2,%ebx
imul   $0x4ec5,%ebx,%eax
mov    %eax,%ecx
shr    $0x1f,%ecx
shr    $0x13,%eax
add    %ecx,%eax
lea    (%rax,%rax,4),%ecx
lea    (%rcx,%rcx,4),%ecx
add    %eax,%ecx
sub    %ecx,%ebx
add    $0x61,%bl
jmp    1186 <rotate+0x66>
movsbl %bl,%ebp
mov    %ebp,%edi
call   1040 <isupper@plt>
test   %rax,%rax
je     1186 <rotate+0x66>
add    $0xffffffc2,%ebp
imul   $0x4ec5,%ebp,%eax
mov    %eax,%ecx
shr    $0x1f,%ecx
shr    $0x13,%eax
add    %ecx,%eax
lea    (%rax,%rax,4),%ecx
lea    (%rcx,%rcx,4),%ecx
add    %eax,%ecx
sub    %ecx,%ebp
add    $0x41,%bpl
mov    %ebp,%ebx
mov    %ebx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define signext i8 @rotate(i8 signext %0) {
%2 = alloca i8
%3 = alloca i8
store i8 %0, i8* %3
%4 = load i8, i8* %3
%5 = call i64 @islower(i8 signext %4)
%6 = icmp ne i64 %5, 0
br i1 %6, label %7, label %15
7: ; preds = %1
%8 = load i8, i8* %3
%9 = sext i8 %8 to i32
%10 = sub nsw i32 %9, 97
%11 = add nsw i32 %10, 3
%12 = srem i32 %11, 26
%13 = add nsw i32 97, %12
%14 = trunc i32 %13 to i8
store i8 %14, i8* %2
br label %29
15: ; preds = %1
%16 = load i8, i8* %3
%17 = call i64 @isupper(i8 signext %16)
%18 = icmp ne i64 %17, 0
br i1 %18, label %19, label %27
19: ; preds = %15
%20 = load i8, i8* %3
%21 = sext i8 %20 to i32
%22 = sub nsw i32 %21, 65
%23 = add nsw i32 %22, 3
%24 = srem i32 %23, 26
%25 = add nsw i32 65, %24
%26 = trunc i32 %25 to i8
store i8 %26, i8* %2
br label %29
27: ; preds = %15
%28 = load i8, i8* %3
store i8 %28, i8* %2
br label %29
29: ; preds = %27, %19, %7
%30 = load i8, i8* %2
ret i8 %30
}

LLVM IR (-O2):
define signext i8 @rotate(i8 signext %0) {
%2 = tail call i64 @islower(i8 signext %0)
%3 = icmp eq i64 %2, 0
br i1 %3, label %10, label %4
4: ; preds = %1
%5 = sext i8 %0 to i16
%6 = add nsw i16 %5, -94
%7 = srem i16 %6, 26
%8 = trunc i16 %7 to i8
%9 = add nsw i8 %8, 97
br label %19
10: ; preds = %1
%11 = tail call i64 @isupper(i8 signext %0)
%12 = icmp eq i64 %11, 0
br i1 %12, label %19, label %13
13: ; preds = %10
%14 = sext i8 %0 to i16
%15 = add nsw i16 %14, -62
%16 = srem i16 %15, 26
%17 = trunc i16 %16 to i8
%18 = add nsw i8 %17, 65
br label %19
19: ; preds = %10, %13, %4
%20 = phi i8 [ %9, %4 ], [ %18, %13 ], [ %0, %10 ]
ret i8 %20
}