#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 */
int function_1(int, int);
int /*<<< orphan*/ printf(char *, ...);
void part2(int x, int y) {
  int i, j, s, t;
  s = i = x;
  t = j = y;
  printf("function_1(x, y) = %d\nmacro_2(x, y) = %d\n\n", function_1(++i, ++j),
         (2 * ++s + 3 * ++t + 4 * ++s * ++t - ++s * ++t * 5));
  printf(
      "In VS : the result of function_1(x, y) = -2 and macro_2(x, y) = -18 \n");
  printf("In GCC: the result of function_1(x, y) = -2 and macro_2(x, y) = -84 "
         "\n\n");
  printf("Explanation: One explination for the variation could be attributed "
         "to how the macro equations expand (order of evaluation & value "
         "production). The order of evaluation is completely compiler "
         "dependent so in this case the way GCC goes through the macro could "
         "be different from VS. Adding auto keywords such as ++ could be buggy "
         "when moving from compiler to compiler. \n\n");
}


x86 assembly (clang, -O0):
<part2>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    -0x4(%rbp),%eax
mov    %eax,-0xc(%rbp)
mov    %eax,-0x14(%rbp)
mov    -0x8(%rbp),%eax
mov    %eax,-0x10(%rbp)
mov    %eax,-0x18(%rbp)
mov    -0xc(%rbp),%edi
add    $0x1,%edi
mov    %edi,-0xc(%rbp)
mov    -0x10(%rbp),%esi
add    $0x1,%esi
mov    %esi,-0x10(%rbp)
call   1040 <function_1@plt>
mov    %eax,%esi
mov    -0x14(%rbp),%edx
add    $0x1,%edx
mov    %edx,-0x14(%rbp)
shl    $0x1,%edx
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
imul   $0x3,%eax,%eax
add    %eax,%edx
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
shl    $0x2,%eax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
mov    %ecx,-0x18(%rbp)
imul   %ecx,%eax
add    %eax,%edx
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
mov    %ecx,-0x18(%rbp)
imul   %ecx,%eax
imul   $0x5,%eax,%eax
sub    %eax,%edx
lea    0xe52(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xe6f(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xea7(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
lea    0xee0(%rip),%rdi
mov    $0x0,%al
call   1030 <printf@plt>
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<part2>:
push   %r15
push   %r14
push   %rbx
mov    %esi,%ebx
mov    %edi,%r14d
lea    0x1(%r14),%edi
lea    0x1(%rbx),%r15d
mov    %r15d,%esi
call   1050 <function_1@plt>
lea    (%r15,%r15,2),%ecx
lea    (%rcx,%r14,2),%ecx
add    $0x2,%ecx
lea    0x8(,%r14,4),%edx
lea    0x2(%rbx),%esi
imul   %edx,%esi
add    %ecx,%esi
add    $0x3,%ebx
lea    (%r14,%r14,4),%ecx
mov    $0xfffffff1,%edx
sub    %ecx,%edx
imul   %ebx,%edx
add    %esi,%edx
lea    0xe81(%rip),%rdi
mov    %eax,%esi
xor    %eax,%eax
call   1040 <printf@plt>
lea    0xe9c(%rip),%rdi
call   1030 <puts@plt>
lea    0xed5(%rip),%rdi
call   1030 <puts@plt>
lea    0xf0f(%rip),%rdi
pop    %rbx
pop    %r14
pop    %r15
jmp    1030 <puts@plt>

LLVM IR (-O0):
@.str = [43 x i8] c"function_1(x, y) = %d\0Amacro_2(x, y) = %d\0A\0A\00"
@.str.1 = [70 x i8] c"In VS : the result of function_1(x, y) = -2 and macro_2(x, y) = -18 \0A\00"
@.str.2 = [71 x i8] c"In GCC: the result of function_1(x, y) = -2 and macro_2(x, y) = -84 \0A\0A\00"
@.str.3 = [368 x i8] c"Explanation: One explination for the variation could be attributed to how the macro equations expand (order of evaluation & value production). The order of evaluation is completely compiler dependent so in this case the way GCC goes through the macro could be different from VS. Adding auto keywords such as ++ could be buggy when moving from compiler to compiler. \0A\0A\00"
define void @part2(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
store i32 %0, i32* %3
store i32 %1, i32* %4
%9 = load i32, i32* %3
store i32 %9, i32* %5
store i32 %9, i32* %7
%10 = load i32, i32* %4
store i32 %10, i32* %6
store i32 %10, i32* %8
%11 = load i32, i32* %5
%12 = add nsw i32 %11, 1
store i32 %12, i32* %5
%13 = load i32, i32* %6
%14 = add nsw i32 %13, 1
store i32 %14, i32* %6
%15 = call i32 @function_1(i32 %12, i32 %14)
%16 = load i32, i32* %7
%17 = add nsw i32 %16, 1
store i32 %17, i32* %7
%18 = mul nsw i32 2, %17
%19 = load i32, i32* %8
%20 = add nsw i32 %19, 1
store i32 %20, i32* %8
%21 = mul nsw i32 3, %20
%22 = add nsw i32 %18, %21
%23 = load i32, i32* %7
%24 = add nsw i32 %23, 1
store i32 %24, i32* %7
%25 = mul nsw i32 4, %24
%26 = load i32, i32* %8
%27 = add nsw i32 %26, 1
store i32 %27, i32* %8
%28 = mul nsw i32 %25, %27
%29 = add nsw i32 %22, %28
%30 = load i32, i32* %7
%31 = add nsw i32 %30, 1
store i32 %31, i32* %7
%32 = load i32, i32* %8
%33 = add nsw i32 %32, 1
store i32 %33, i32* %8
%34 = mul nsw i32 %31, %33
%35 = mul nsw i32 %34, 5
%36 = sub nsw i32 %29, %35
%37 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str, i64 0, i64 0), i32 %15, i32 %36)
%38 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([70 x i8], [70 x i8]* @.str.1, i64 0, i64 0))
%39 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([71 x i8], [71 x i8]* @.str.2, i64 0, i64 0))
%40 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([368 x i8], [368 x i8]* @.str.3, i64 0, i64 0))
ret void
}

LLVM IR (-O2):
@.str = [43 x i8] c"function_1(x, y) = %d\0Amacro_2(x, y) = %d\0A\0A\00"
@str = [69 x i8] c"In VS : the result of function_1(x, y) = -2 and macro_2(x, y) = -18 \00"
@str.4 = [70 x i8] c"In GCC: the result of function_1(x, y) = -2 and macro_2(x, y) = -84 \0A\00"
@str.5 = [367 x i8] c"Explanation: One explination for the variation could be attributed to how the macro equations expand (order of evaluation & value production). The order of evaluation is completely compiler dependent so in this case the way GCC goes through the macro could be different from VS. Adding auto keywords such as ++ could be buggy when moving from compiler to compiler. \0A\00"
define void @part2(i32 %0, i32 %1) {
%3 = add nsw i32 %0, 1
%4 = add nsw i32 %1, 1
%5 = tail call i32 @function_1(i32 %3, i32 %4)
%6 = shl nsw i32 %3, 1
%7 = mul nsw i32 %4, 3
%8 = add nsw i32 %7, %6
%9 = shl i32 %0, 2
%10 = add i32 %9, 8
%11 = add nsw i32 %1, 2
%12 = mul nsw i32 %10, %11
%13 = add nsw i32 %8, %12
%14 = add nsw i32 %1, 3
%15 = mul i32 %0, -5
%16 = add i32 %15, -15
%17 = mul i32 %16, %14
%18 = add i32 %13, %17
%19 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([43 x i8], [43 x i8]* @.str, i64 0, i64 0), i32 %5, i32 %18)
%20 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([69 x i8], [69 x i8]* @str, i64 0, i64 0))
%21 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([70 x i8], [70 x i8]* @str.4, i64 0, i64 0))
%22 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([367 x i8], [367 x i8]* @str.5, i64 0, i64 0))
ret void
}