blob: 847e81755939f5ad6bc4a28a20214a5e95275256 [file] [log] [blame]
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll
// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM
// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll
// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG
void b0(int a, int b) {
int x = a * b;
x = x / b;
x = x % b;
x = x + b;
x = x - b;
x = x & b;
x = x ^ b;
x = x | b;
}
// CIR-LABEL: cir.func{{.*}} @_Z2b0ii(
// CIR: %{{.+}} = cir.binop(mul, %{{.+}}, %{{.+}}) nsw : !s32i
// CIR: %{{.+}} = cir.binop(div, %{{.+}}, %{{.+}}) : !s32i
// CIR: %{{.+}} = cir.binop(rem, %{{.+}}, %{{.+}}) : !s32i
// CIR: %{{.+}} = cir.binop(add, %{{.+}}, %{{.+}}) nsw : !s32i
// CIR: %{{.+}} = cir.binop(sub, %{{.+}}, %{{.+}}) nsw : !s32i
// CIR: %{{.+}} = cir.binop(and, %{{.+}}, %{{.+}}) : !s32i
// CIR: %{{.+}} = cir.binop(xor, %{{.+}}, %{{.+}}) : !s32i
// CIR: %{{.+}} = cir.binop(or, %{{.+}}, %{{.+}}) : !s32i
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z2b0ii(
// LLVM-SAME: i32 %[[A:.*]], i32 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i32
// LLVM: %[[B_ADDR:.*]] = alloca i32
// LLVM: %[[X:.*]] = alloca i32
// LLVM: store i32 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i32 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[MUL:.*]] = mul nsw i32 %[[A]], %[[B]]
// LLVM: store i32 %[[MUL]], ptr %[[X]]
// LLVM: %[[X1:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[DIV:.*]] = sdiv i32 %[[X1]], %[[B1]]
// LLVM: store i32 %[[DIV]], ptr %[[X]]
// LLVM: %[[X2:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[REM:.*]] = srem i32 %[[X2]], %[[B2]]
// LLVM: store i32 %[[REM]], ptr %[[X]]
// LLVM: %[[X3:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B3:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[ADD:.*]] = add nsw i32 %[[X3]], %[[B3]]
// LLVM: store i32 %[[ADD]], ptr %[[X]]
// LLVM: %[[X4:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B4:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[SUB:.*]] = sub nsw i32 %[[X4]], %[[B4]]
// LLVM: store i32 %[[SUB]], ptr %[[X]]
// LLVM: %[[X5:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B5:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[AND:.*]] = and i32 %[[X5]], %[[B5]]
// LLVM: store i32 %[[AND]], ptr %[[X]]
// LLVM: %[[X6:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B6:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[XOR:.*]] = xor i32 %[[X6]], %[[B6]]
// LLVM: store i32 %[[XOR]], ptr %[[X]]
// LLVM: %[[X7:.*]] = load i32, ptr %[[X]]
// LLVM: %[[B7:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[OR:.*]] = or i32 %[[X7]], %[[B7]]
// LLVM: store i32 %[[OR]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z2b0ii(i32 {{.*}} %a, i32 {{.*}} %b) {{.*}} {
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i32
// OGCG: %[[X:.*]] = alloca i32
// OGCG: store i32 %a, ptr %[[A_ADDR]]
// OGCG: store i32 %b, ptr %[[B_ADDR]]
// OGCG: %[[A:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[MUL:.*]] = mul nsw i32 %[[A]], %[[B]]
// OGCG: store i32 %[[MUL]], ptr %[[X]]
// OGCG: %[[X1:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[DIV:.*]] = sdiv i32 %[[X1]], %[[B1]]
// OGCG: store i32 %[[DIV]], ptr %[[X]]
// OGCG: %[[X2:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[REM:.*]] = srem i32 %[[X2]], %[[B2]]
// OGCG: store i32 %[[REM]], ptr %[[X]]
// OGCG: %[[X3:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B3:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[ADD:.*]] = add nsw i32 %[[X3]], %[[B3]]
// OGCG: store i32 %[[ADD]], ptr %[[X]]
// OGCG: %[[X4:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B4:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[SUB:.*]] = sub nsw i32 %[[X4]], %[[B4]]
// OGCG: store i32 %[[SUB]], ptr %[[X]]
// OGCG: %[[X5:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B5:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[AND:.*]] = and i32 %[[X5]], %[[B5]]
// OGCG: store i32 %[[AND]], ptr %[[X]]
// OGCG: %[[X6:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B6:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[XOR:.*]] = xor i32 %[[X6]], %[[B6]]
// OGCG: store i32 %[[XOR]], ptr %[[X]]
// OGCG: %[[X7:.*]] = load i32, ptr %[[X]]
// OGCG: %[[B7:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[OR:.*]] = or i32 %[[X7]], %[[B7]]
// OGCG: store i32 %[[OR]], ptr %[[X]]
// OGCG: ret void
void testFloatingPointBinOps(float a, float b) {
a * b;
a / b;
a + b;
a - b;
}
// CIR-LABEL: cir.func{{.*}} @_Z23testFloatingPointBinOpsff(
// CIR: cir.binop(mul, %{{.+}}, %{{.+}}) : !cir.float
// CIR: cir.binop(div, %{{.+}}, %{{.+}}) : !cir.float
// CIR: cir.binop(add, %{{.+}}, %{{.+}}) : !cir.float
// CIR: cir.binop(sub, %{{.+}}, %{{.+}}) : !cir.float
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z23testFloatingPointBinOpsff(
// LLVM-SAME: float %[[A:.*]], float %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca float, i64 1
// LLVM: %[[B_ADDR:.*]] = alloca float, i64 1
// LLVM: store float %[[A]], ptr %[[A_ADDR]]
// LLVM: store float %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load float, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load float, ptr %[[B_ADDR]]
// LLVM: fmul float %[[A1]], %[[B1]]
// LLVM: %[[A2:.*]] = load float, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load float, ptr %[[B_ADDR]]
// LLVM: fdiv float %[[A2]], %[[B2]]
// LLVM: %[[A3:.*]] = load float, ptr %[[A_ADDR]]
// LLVM: %[[B3:.*]] = load float, ptr %[[B_ADDR]]
// LLVM: fadd float %[[A3]], %[[B3]]
// LLVM: %[[A4:.*]] = load float, ptr %[[A_ADDR]]
// LLVM: %[[B4:.*]] = load float, ptr %[[B_ADDR]]
// LLVM: fsub float %[[A4]], %[[B4]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z23testFloatingPointBinOpsff(float {{.*}} %a, float {{.*}} %b)
// OGCG: %a.addr = alloca float
// OGCG: %b.addr = alloca float
// OGCG: store float %a, ptr %a.addr
// OGCG: store float %b, ptr %b.addr
// OGCG: %[[A1:.*]] = load float, ptr %a.addr
// OGCG: %[[B1:.*]] = load float, ptr %b.addr
// OGCG: fmul float %[[A1]], %[[B1]]
// OGCG: %[[A2:.*]] = load float, ptr %a.addr
// OGCG: %[[B2:.*]] = load float, ptr %b.addr
// OGCG: fdiv float %[[A2]], %[[B2]]
// OGCG: %[[A3:.*]] = load float, ptr %a.addr
// OGCG: %[[B3:.*]] = load float, ptr %b.addr
// OGCG: fadd float %[[A3]], %[[B3]]
// OGCG: %[[A4:.*]] = load float, ptr %a.addr
// OGCG: %[[B4:.*]] = load float, ptr %b.addr
// OGCG: fsub float %[[A4]], %[[B4]]
// OGCG: ret void
void signed_shift(int a, int b) {
int x = a >> b;
x = a << b;
}
// CIR-LABEL: cir.func{{.*}} @_Z12signed_shiftii(
// CIR-SAME: %[[ARG0:.*]]: !s32i{{.*}}, %[[ARG1:.*]]: !s32i{{.*}})
// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
// CIR: %[[X_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
// CIR: cir.store{{.*}} %[[ARG0]], %[[A_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[ARG1]], %[[B_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[A1:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B1:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[ASHR:.*]] = cir.shift(right, %[[A1]] : !s32i, %[[B1]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[ASHR]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[A2:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B2:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[SHL:.*]] = cir.shift(left, %[[A2]] : !s32i, %[[B2]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[SHL]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z12signed_shiftii
// LLVM-SAME: (i32 %[[A:.*]], i32 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i32
// LLVM: %[[B_ADDR:.*]] = alloca i32
// LLVM: %[[X:.*]] = alloca i32
// LLVM: store i32 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i32 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1]]
// LLVM: store i32 %[[ASHR]], ptr %[[X]]
// LLVM: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2]]
// LLVM: store i32 %[[SHL]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z12signed_shiftii
// OGCG-SAME: (i32 {{.*}} %[[A:.*]], i32 {{.*}} %[[B:.*]])
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i32
// OGCG: %[[X:.*]] = alloca i32
// OGCG: store i32 %[[A]], ptr %[[A_ADDR]]
// OGCG: store i32 %[[B]], ptr %[[B_ADDR]]
// OGCG: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1]]
// OGCG: store i32 %[[ASHR]], ptr %[[X]]
// OGCG: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2]]
// OGCG: store i32 %[[SHL]], ptr %[[X]]
// OGCG: ret void
void unsigned_shift(unsigned a, unsigned b) {
unsigned x = a >> b;
x = a << b;
}
// CIR-LABEL: cir.func{{.*}} @_Z14unsigned_shiftjj(
// CIR-SAME: %[[ARG0:.*]]: !u32i{{.*}}, %[[ARG1:.*]]: !u32i{{.*}})
// CIR: %[[A_PTR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["b", init]
// CIR: %[[X_PTR:.*]] = cir.alloca !u32i, !cir.ptr<!u32i>, ["x", init]
// CIR: cir.store{{.*}} %[[ARG0]], %[[A_PTR]] : !u32i, !cir.ptr<!u32i>
// CIR: cir.store{{.*}} %[[ARG1]], %[[B_PTR]] : !u32i, !cir.ptr<!u32i>
// CIR: %[[A1:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!u32i>, !u32i
// CIR: %[[B1:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!u32i>, !u32i
// CIR: %[[ASHR:.*]] = cir.shift(right, %[[A1]] : !u32i, %[[B1]] : !u32i) -> !u32i
// CIR: cir.store{{.*}} %[[ASHR]], %[[X_PTR]] : !u32i, !cir.ptr<!u32i>
// CIR: %[[A2:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!u32i>, !u32i
// CIR: %[[B2:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!u32i>, !u32i
// CIR: %[[SHL:.*]] = cir.shift(left, %[[A2]] : !u32i, %[[B2]] : !u32i) -> !u32i
// CIR: cir.store{{.*}} %[[SHL]], %[[X_PTR]] : !u32i, !cir.ptr<!u32i>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z14unsigned_shiftjj
// LLVM-SAME: (i32 %[[A:.*]], i32 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i32
// LLVM: %[[B_ADDR:.*]] = alloca i32
// LLVM: %[[X:.*]] = alloca i32
// LLVM: store i32 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i32 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[ASHR:.*]] = lshr i32 %[[A1]], %[[B1]]
// LLVM: store i32 %[[ASHR]], ptr %[[X]]
// LLVM: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2]]
// LLVM: store i32 %[[SHL]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z14unsigned_shiftjj
// OGCG-SAME: (i32 {{.*}} %[[A:.*]], i32 {{.*}} %[[B:.*]])
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i32
// OGCG: %[[X:.*]] = alloca i32
// OGCG: store i32 %[[A]], ptr %[[A_ADDR]]
// OGCG: store i32 %[[B]], ptr %[[B_ADDR]]
// OGCG: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B1:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[ASHR:.*]] = lshr i32 %[[A1]], %[[B1]]
// OGCG: store i32 %[[ASHR]], ptr %[[X]]
// OGCG: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B2:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2]]
// OGCG: store i32 %[[SHL]], ptr %[[X]]
// OGCG: ret void
void zext_shift_example(int a, unsigned char b) {
int x = a >> b;
x = a << b;
}
// CIR-LABEL: cir.func{{.*}} @_Z18zext_shift_exampleih(
// CIR-SAME: %[[ARG0:.*]]: !s32i{{.*}}, %[[ARG1:.*]]: !u8i{{.*}})
// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !u8i, !cir.ptr<!u8i>, ["b", init]
// CIR: %[[X_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
// CIR: cir.store{{.*}} %[[ARG0]], %[[A_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[ARG1]], %[[B_PTR]] : !u8i, !cir.ptr<!u8i>
// CIR: %[[A1:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B1:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!u8i>, !u8i
// CIR: %[[B1_EXT:.*]] = cir.cast(integral, %[[B1]] : !u8i), !s32i
// CIR: %[[ASHR:.*]] = cir.shift(right, %[[A1]] : !s32i, %[[B1_EXT]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[ASHR]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[A2:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B2:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!u8i>, !u8i
// CIR: %[[B2_EXT:.*]] = cir.cast(integral, %[[B2]] : !u8i), !s32i
// CIR: %[[SHL:.*]] = cir.shift(left, %[[A2]] : !s32i, %[[B2_EXT]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[SHL]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z18zext_shift_exampleih
// LLVM-SAME: (i32 %[[A:.*]], i8 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i32
// LLVM: %[[B_ADDR:.*]] = alloca i8
// LLVM: %[[X:.*]] = alloca i32
// LLVM: store i32 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i8 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B1_EXT:.*]] = zext i8 %[[B1]] to i32
// LLVM: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1_EXT]]
// LLVM: store i32 %[[ASHR]], ptr %[[X]]
// LLVM: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B2_EXT:.*]] = zext i8 %[[B2]] to i32
// LLVM: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2_EXT]]
// LLVM: store i32 %[[SHL]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z18zext_shift_exampleih
// OGCG-SAME: (i32 {{.*}} %[[A:.*]], i8 {{.*}} %[[B:.*]])
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i8
// OGCG: %[[X:.*]] = alloca i32
// OGCG: store i32 %[[A]], ptr %[[A_ADDR]]
// OGCG: store i8 %[[B]], ptr %[[B_ADDR]]
// OGCG: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B1:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B1_EXT:.*]] = zext i8 %[[B1]] to i32
// OGCG: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1_EXT]]
// OGCG: store i32 %[[ASHR]], ptr %[[X]]
// OGCG: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B2:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B2_EXT:.*]] = zext i8 %[[B2]] to i32
// OGCG: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2_EXT]]
// OGCG: store i32 %[[SHL]], ptr %[[X]]
// OGCG: ret void
void sext_shift_example(int a, signed char b) {
int x = a >> b;
x = a << b;
}
// CIR-LABEL: cir.func{{.*}} @_Z18sext_shift_exampleia(
// CIR-SAME: %[[ARG0:.*]]: !s32i{{.*}}, %[[ARG1:.*]]: !s8i{{.*}})
// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !s8i, !cir.ptr<!s8i>, ["b", init]
// CIR: %[[X_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]
// CIR: cir.store{{.*}} %[[ARG0]], %[[A_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store{{.*}} %[[ARG1]], %[[B_PTR]] : !s8i, !cir.ptr<!s8i>
// CIR: %[[A1:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B1:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s8i>, !s8i
// CIR: %[[B1_EXT:.*]] = cir.cast(integral, %[[B1]] : !s8i), !s32i
// CIR: %[[ASHR:.*]] = cir.shift(right, %[[A1]] : !s32i, %[[B1_EXT]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[ASHR]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: %[[A2:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i
// CIR: %[[B2:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s8i>, !s8i
// CIR: %[[B2_EXT:.*]] = cir.cast(integral, %[[B2]] : !s8i), !s32i
// CIR: %[[SHL:.*]] = cir.shift(left, %[[A2]] : !s32i, %[[B2_EXT]] : !s32i) -> !s32i
// CIR: cir.store{{.*}} %[[SHL]], %[[X_PTR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z18sext_shift_exampleia
// LLVM-SAME: (i32 %[[A:.*]], i8 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i32
// LLVM: %[[B_ADDR:.*]] = alloca i8
// LLVM: %[[X:.*]] = alloca i32
// LLVM: store i32 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i8 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B1_EXT:.*]] = sext i8 %[[B1]] to i32
// LLVM: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1_EXT]]
// LLVM: store i32 %[[ASHR]], ptr %[[X]]
// LLVM: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B2_EXT:.*]] = sext i8 %[[B2]] to i32
// LLVM: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2_EXT]]
// LLVM: store i32 %[[SHL]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z18sext_shift_exampleia
// OGCG-SAME: (i32 {{.*}} %[[A:.*]], i8 {{.*}} %[[B:.*]])
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i8
// OGCG: %[[X:.*]] = alloca i32
// OGCG: store i32 %[[A]], ptr %[[A_ADDR]]
// OGCG: store i8 %[[B]], ptr %[[B_ADDR]]
// OGCG: %[[A1:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B1:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B1_EXT:.*]] = sext i8 %[[B1]] to i32
// OGCG: %[[ASHR:.*]] = ashr i32 %[[A1]], %[[B1_EXT]]
// OGCG: store i32 %[[ASHR]], ptr %[[X]]
// OGCG: %[[A2:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B2:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B2_EXT:.*]] = sext i8 %[[B2]] to i32
// OGCG: %[[SHL:.*]] = shl i32 %[[A2]], %[[B2_EXT]]
// OGCG: store i32 %[[SHL]], ptr %[[X]]
// OGCG: ret void
void long_shift_example(long long a, short b) {
long long x = a >> b;
x = a << b;
}
// CIR-LABEL: cir.func{{.*}} @_Z18long_shift_examplexs(
// CIR-SAME: %[[ARG0:.*]]: !s64i{{.*}}, %[[ARG1:.*]]: !s16i{{.*}})
// CIR: %[[A_PTR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["a", init]
// CIR: %[[B_PTR:.*]] = cir.alloca !s16i, !cir.ptr<!s16i>, ["b", init]
// CIR: %[[X_PTR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["x", init]
// CIR: cir.store{{.*}} %[[ARG0]], %[[A_PTR]] : !s64i, !cir.ptr<!s64i>
// CIR: cir.store{{.*}} %[[ARG1]], %[[B_PTR]] : !s16i, !cir.ptr<!s16i>
// CIR: %[[A1:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s64i>, !s64i
// CIR: %[[B1:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s16i>, !s16i
// CIR: %[[B1_EXT:.*]] = cir.cast(integral, %[[B1]] : !s16i), !s32i
// CIR: %[[ASHR:.*]] = cir.shift(right, %[[A1]] : !s64i, %[[B1_EXT]] : !s32i) -> !s64i
// CIR: cir.store{{.*}} %[[ASHR]], %[[X_PTR]] : !s64i, !cir.ptr<!s64i>
// CIR: %[[A2:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s64i>, !s64i
// CIR: %[[B2:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s16i>, !s16i
// CIR: %[[B2_EXT:.*]] = cir.cast(integral, %[[B2]] : !s16i), !s32i
// CIR: %[[SHL:.*]] = cir.shift(left, %[[A2]] : !s64i, %[[B2_EXT]] : !s32i) -> !s64i
// CIR: cir.store{{.*}} %[[SHL]], %[[X_PTR]] : !s64i, !cir.ptr<!s64i>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z18long_shift_examplexs
// LLVM-SAME: (i64 %[[A:.*]], i16 %[[B:.*]])
// LLVM: %[[A_ADDR:.*]] = alloca i64
// LLVM: %[[B_ADDR:.*]] = alloca i16
// LLVM: %[[X:.*]] = alloca i64
// LLVM: store i64 %[[A]], ptr %[[A_ADDR]]
// LLVM: store i16 %[[B]], ptr %[[B_ADDR]]
// LLVM: %[[A1:.*]] = load i64, ptr %[[A_ADDR]]
// LLVM: %[[B1:.*]] = load i16, ptr %[[B_ADDR]]
// LLVM: %[[B1_SEXT:.*]] = sext i16 %[[B1]] to i32
// LLVM: %[[B1_ZEXT:.*]] = zext i32 %[[B1_SEXT]] to i64
// LLVM: %[[ASHR:.*]] = ashr i64 %[[A1]], %[[B1_ZEXT]]
// LLVM: store i64 %[[ASHR]], ptr %[[X]]
// LLVM: %[[A2:.*]] = load i64, ptr %[[A_ADDR]]
// LLVM: %[[B2:.*]] = load i16, ptr %[[B_ADDR]]
// LLVM: %[[B2_SEXT:.*]] = sext i16 %[[B2]] to i32
// LLVM: %[[B2_ZEXT:.*]] = zext i32 %[[B2_SEXT]] to i64
// LLVM: %[[SHL:.*]] = shl i64 %[[A2]], %[[B2_ZEXT]]
// LLVM: store i64 %[[SHL]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z18long_shift_examplexs
// OGCG-SAME: (i64 {{.*}} %[[A:.*]], i16 {{.*}} %[[B:.*]])
// OGCG: %[[A_ADDR:.*]] = alloca i64
// OGCG: %[[B_ADDR:.*]] = alloca i16
// OGCG: %[[X:.*]] = alloca i64
// OGCG: store i64 %[[A]], ptr %[[A_ADDR]]
// OGCG: store i16 %[[B]], ptr %[[B_ADDR]]
// OGCG: %[[A1:.*]] = load i64, ptr %[[A_ADDR]]
// OGCG: %[[B1:.*]] = load i16, ptr %[[B_ADDR]]
// OGCG: %[[B1_SEXT:.*]] = sext i16 %[[B1]] to i32
// OGCG: %[[B1_ZEXT:.*]] = zext i32 %[[B1_SEXT]] to i64
// OGCG: %[[ASHR:.*]] = ashr i64 %[[A1]], %[[B1_ZEXT]]
// OGCG: store i64 %[[ASHR]], ptr %[[X]]
// OGCG: %[[A2:.*]] = load i64, ptr %[[A_ADDR]]
// OGCG: %[[B2:.*]] = load i16, ptr %[[B_ADDR]]
// OGCG: %[[B2_SEXT:.*]] = sext i16 %[[B2]] to i32
// OGCG: %[[B2_ZEXT:.*]] = zext i32 %[[B2_SEXT]] to i64
// OGCG: %[[SHL:.*]] = shl i64 %[[A2]], %[[B2_ZEXT]]
// OGCG: store i64 %[[SHL]], ptr %[[X]]
// OGCG: ret void
void b1(bool a, bool b) {
bool x = a && b;
x = x || b;
}
// CIR-LABEL: cir.func{{.*}} @_Z2b1bb(
// CIR-SAME: %[[ARG0:.*]]: !cir.bool {{.*}}, %[[ARG1:.*]]: !cir.bool {{.*}})
// CIR: [[A:%[0-9]+]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["a", init]
// CIR: [[B:%[0-9]+]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["b", init]
// CIR: [[X:%[0-9]+]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["x", init]
// CIR: cir.store %[[ARG0]], [[A]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: cir.store %[[ARG1]], [[B]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: [[AVAL:%[0-9]+]] = cir.load align(1) [[A]] : !cir.ptr<!cir.bool>, !cir.bool
// CIR: [[RES1:%[0-9]+]] = cir.ternary([[AVAL]], true {
// CIR: [[BVAL:%[0-9]+]] = cir.load align(1) [[B]] : !cir.ptr<!cir.bool>, !cir.bool
// CIR: cir.yield [[BVAL]] : !cir.bool
// CIR: }, false {
// CIR: [[FALSE:%[0-9]+]] = cir.const #false
// CIR: cir.yield [[FALSE]] : !cir.bool
// CIR: }) : (!cir.bool) -> !cir.bool
// CIR: cir.store align(1) [[RES1]], [[X]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: [[XVAL:%[0-9]+]] = cir.load align(1) [[X]] : !cir.ptr<!cir.bool>, !cir.bool
// CIR: [[RES2:%[0-9]+]] = cir.ternary([[XVAL]], true {
// CIR: [[TRUE:%[0-9]+]] = cir.const #true
// CIR: cir.yield [[TRUE]] : !cir.bool
// CIR: }, false {
// CIR: [[BVAL2:%[0-9]+]] = cir.load align(1) [[B]] : !cir.ptr<!cir.bool>, !cir.bool
// CIR: cir.yield [[BVAL2]] : !cir.bool
// CIR: }) : (!cir.bool) -> !cir.bool
// CIR: cir.store align(1) [[RES2]], [[X]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z2b1bb(
// LLVM-SAME: i1 %[[ARG0:.+]], i1 %[[ARG1:.+]])
// LLVM: %[[A_ADDR:.*]] = alloca i8
// LLVM: %[[B_ADDR:.*]] = alloca i8
// LLVM: %[[X:.*]] = alloca i8
// LLVM: %[[ZEXT0:.*]] = zext i1 %[[ARG0]] to i8
// LLVM: store i8 %[[ZEXT0]], ptr %[[A_ADDR]]
// LLVM: %[[ZEXT1:.*]] = zext i1 %[[ARG1]] to i8
// LLVM: store i8 %[[ZEXT1]], ptr %[[B_ADDR]]
// LLVM: %[[A_VAL:.*]] = load i8, ptr %[[A_ADDR]]
// LLVM: %[[A_BOOL:.*]] = trunc i8 %[[A_VAL]] to i1
// LLVM: br i1 %[[A_BOOL]], label %[[AND_TRUE:.+]], label %[[AND_FALSE:.+]]
// LLVM: [[AND_TRUE]]:
// LLVM: %[[B_VAL:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B_BOOL:.*]] = trunc i8 %[[B_VAL]] to i1
// LLVM: br label %[[AND_MERGE:.+]]
// LLVM: [[AND_FALSE]]:
// LLVM: br label %[[AND_MERGE]]
// LLVM: [[AND_MERGE]]:
// LLVM: %[[AND_PHI:.*]] = phi i1 [ false, %[[AND_FALSE]] ], [ %[[B_BOOL]], %[[AND_TRUE]] ]
// LLVM: %[[ZEXT_AND:.*]] = zext i1 %[[AND_PHI]] to i8
// LLVM: store i8 %[[ZEXT_AND]], ptr %[[X]]
// LLVM: %[[X_VAL:.*]] = load i8, ptr %[[X]]
// LLVM: %[[X_BOOL:.*]] = trunc i8 %[[X_VAL]] to i1
// LLVM: br i1 %[[X_BOOL]], label %[[OR_TRUE:.+]], label %[[OR_FALSE:.+]]
// LLVM: [[OR_TRUE]]:
// LLVM: br label %[[OR_MERGE:.+]]
// LLVM: [[OR_FALSE]]:
// LLVM: %[[B_VAL2:.*]] = load i8, ptr %[[B_ADDR]]
// LLVM: %[[B_BOOL2:.*]] = trunc i8 %[[B_VAL2]] to i1
// LLVM: br label %[[OR_MERGE]]
// LLVM: [[OR_MERGE]]:
// LLVM: %[[OR_PHI:.*]] = phi i1 [ %[[B_BOOL2]], %[[OR_FALSE]] ], [ true, %[[OR_TRUE]] ]
// LLVM: %[[ZEXT_OR:.*]] = zext i1 %[[OR_PHI]] to i8
// LLVM: store i8 %[[ZEXT_OR]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z2b1bb
// OGCG-SAME: (i1 {{.*}} %[[ARG0:.+]], i1 {{.*}} %[[ARG1:.+]])
// OGCG: [[ENTRY:.*]]:
// OGCG: %[[A_ADDR:.*]] = alloca i8
// OGCG: %[[B_ADDR:.*]] = alloca i8
// OGCG: %[[X:.*]] = alloca i8
// OGCG: %[[ZEXT0:.*]] = zext i1 %[[ARG0]] to i8
// OGCG: store i8 %[[ZEXT0]], ptr %[[A_ADDR]]
// OGCG: %[[ZEXT1:.*]] = zext i1 %[[ARG1]] to i8
// OGCG: store i8 %[[ZEXT1]], ptr %[[B_ADDR]]
// OGCG: %[[A_VAL:.*]] = load i8, ptr %[[A_ADDR]]
// OGCG: %[[A_BOOL:.*]] = trunc i8 %[[A_VAL]] to i1
// OGCG: br i1 %[[A_BOOL]], label %[[AND_TRUE:.+]], label %[[AND_MERGE:.+]]
// OGCG: [[AND_TRUE]]:
// OGCG: %[[B_VAL:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B_BOOL:.*]] = trunc i8 %[[B_VAL]] to i1
// OGCG: br label %[[AND_MERGE:.+]]
// OGCG: [[AND_MERGE]]:
// OGCG: %[[AND_PHI:.*]] = phi i1 [ false, %[[ENTRY]] ], [ %[[B_BOOL]], %[[AND_TRUE]] ]
// OGCG: %[[ZEXT_AND:.*]] = zext i1 %[[AND_PHI]] to i8
// OGCG: store i8 %[[ZEXT_AND]], ptr %[[X]]
// OGCG: %[[X_VAL:.*]] = load i8, ptr %[[X]]
// OGCG: %[[X_BOOL:.*]] = trunc i8 %[[X_VAL]] to i1
// OGCG: br i1 %[[X_BOOL]], label %[[OR_MERGE:.+]], label %[[OR_FALSE:.+]]
// OGCG: [[OR_FALSE]]:
// OGCG: %[[B_VAL2:.*]] = load i8, ptr %[[B_ADDR]]
// OGCG: %[[B_BOOL2:.*]] = trunc i8 %[[B_VAL2]] to i1
// OGCG: br label %[[OR_MERGE]]
// OGCG: [[OR_MERGE]]:
// OGCG: %[[OR_PHI:.*]] = phi i1 [ true, %[[AND_MERGE]] ], [ %[[B_BOOL2]], %[[OR_FALSE]] ]
// OGCG: %[[ZEXT_OR:.*]] = zext i1 %[[OR_PHI]] to i8
// OGCG: store i8 %[[ZEXT_OR]], ptr %[[X]]
// OGCG: ret void
void b3(int a, int b, int c, int d) {
bool x = (a == b) && (c == d);
x = (a == b) || (c == d);
}
// CIR-LABEL: cir.func{{.*}} @_Z2b3iiii(
// CIR-SAME: %[[ARG0:.*]]: !s32i {{.*}}, %[[ARG1:.*]]: !s32i {{.*}}, %[[ARG2:.*]]: !s32i {{.*}}, %[[ARG3:.*]]: !s32i {{.*}})
// CIR: [[A:%[0-9]+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]
// CIR: [[B:%[0-9]+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]
// CIR: [[C:%[0-9]+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init]
// CIR: [[D:%[0-9]+]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["d", init]
// CIR: [[X:%[0-9]+]] = cir.alloca !cir.bool, !cir.ptr<!cir.bool>, ["x", init]
// CIR: cir.store %[[ARG0]], [[A]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store %[[ARG1]], [[B]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store %[[ARG2]], [[C]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.store %[[ARG3]], [[D]] : !s32i, !cir.ptr<!s32i>
// CIR: [[AVAL1:%[0-9]+]] = cir.load align(4) [[A]] : !cir.ptr<!s32i>, !s32i
// CIR: [[BVAL1:%[0-9]+]] = cir.load align(4) [[B]] : !cir.ptr<!s32i>, !s32i
// CIR: [[CMP1:%[0-9]+]] = cir.cmp(eq, [[AVAL1]], [[BVAL1]]) : !s32i, !cir.bool
// CIR: [[AND_RESULT:%[0-9]+]] = cir.ternary([[CMP1]], true {
// CIR: [[CVAL1:%[0-9]+]] = cir.load align(4) [[C]] : !cir.ptr<!s32i>, !s32i
// CIR: [[DVAL1:%[0-9]+]] = cir.load align(4) [[D]] : !cir.ptr<!s32i>, !s32i
// CIR: [[CMP2:%[0-9]+]] = cir.cmp(eq, [[CVAL1]], [[DVAL1]]) : !s32i, !cir.bool
// CIR: cir.yield [[CMP2]] : !cir.bool
// CIR: }, false {
// CIR: [[FALSE:%[0-9]+]] = cir.const #false
// CIR: cir.yield [[FALSE]] : !cir.bool
// CIR: }) : (!cir.bool) -> !cir.bool
// CIR: cir.store align(1) [[AND_RESULT]], [[X]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: [[AVAL2:%[0-9]+]] = cir.load align(4) [[A]] : !cir.ptr<!s32i>, !s32i
// CIR: [[BVAL2:%[0-9]+]] = cir.load align(4) [[B]] : !cir.ptr<!s32i>, !s32i
// CIR: [[CMP3:%[0-9]+]] = cir.cmp(eq, [[AVAL2]], [[BVAL2]]) : !s32i, !cir.bool
// CIR: [[OR_RESULT:%[0-9]+]] = cir.ternary([[CMP3]], true {
// CIR: [[TRUE:%[0-9]+]] = cir.const #true
// CIR: cir.yield [[TRUE]] : !cir.bool
// CIR: }, false {
// CIR: [[CVAL2:%[0-9]+]] = cir.load align(4) [[C]] : !cir.ptr<!s32i>, !s32i
// CIR: [[DVAL2:%[0-9]+]] = cir.load align(4) [[D]] : !cir.ptr<!s32i>, !s32i
// CIR: [[CMP4:%[0-9]+]] = cir.cmp(eq, [[CVAL2]], [[DVAL2]]) : !s32i, !cir.bool
// CIR: cir.yield [[CMP4]] : !cir.bool
// CIR: }) : (!cir.bool) -> !cir.bool
// CIR: cir.store align(1) [[OR_RESULT]], [[X]] : !cir.bool, !cir.ptr<!cir.bool>
// CIR: cir.return
// LLVM-LABEL: define{{.*}} void @_Z2b3iiii(
// LLVM-SAME: i32 %[[ARG0:.+]], i32 %[[ARG1:.+]], i32 %[[ARG2:.+]], i32 %[[ARG3:.+]])
// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1
// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1
// LLVM: %[[C_ADDR:.*]] = alloca i32, i64 1
// LLVM: %[[D_ADDR:.*]] = alloca i32, i64 1
// LLVM: %[[X:.*]] = alloca i8, i64 1
// LLVM: store i32 %[[ARG0]], ptr %[[A_ADDR]]
// LLVM: store i32 %[[ARG1]], ptr %[[B_ADDR]]
// LLVM: store i32 %[[ARG2]], ptr %[[C_ADDR]]
// LLVM: store i32 %[[ARG3]], ptr %[[D_ADDR]]
// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B_VAL:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[CMP1:.*]] = icmp eq i32 %[[A_VAL]], %[[B_VAL]]
// LLVM: br i1 %[[CMP1]], label %[[AND_TRUE:.+]], label %[[AND_FALSE:.+]]
// LLVM: [[AND_TRUE]]:
// LLVM: %[[C_VAL:.*]] = load i32, ptr %[[C_ADDR]]
// LLVM: %[[D_VAL:.*]] = load i32, ptr %[[D_ADDR]]
// LLVM: %[[CMP2:.*]] = icmp eq i32 %[[C_VAL]], %[[D_VAL]]
// LLVM: br label %[[AND_MERGE:.+]]
// LLVM: [[AND_FALSE]]:
// LLVM: br label %[[AND_MERGE]]
// LLVM: [[AND_MERGE]]:
// LLVM: %[[AND_PHI:.*]] = phi i1 [ false, %[[AND_FALSE]] ], [ %[[CMP2]], %[[AND_TRUE]] ]
// LLVM: %[[ZEXT_AND:.*]] = zext i1 %[[AND_PHI]] to i8
// LLVM: store i8 %[[ZEXT_AND]], ptr %[[X]]
// LLVM: %[[A_VAL2:.*]] = load i32, ptr %[[A_ADDR]]
// LLVM: %[[B_VAL2:.*]] = load i32, ptr %[[B_ADDR]]
// LLVM: %[[CMP3:.*]] = icmp eq i32 %[[A_VAL2]], %[[B_VAL2]]
// LLVM: br i1 %[[CMP3]], label %[[OR_TRUE:.+]], label %[[OR_FALSE:.+]]
// LLVM: [[OR_TRUE]]:
// LLVM: br label %[[OR_MERGE:.+]]
// LLVM: [[OR_FALSE]]:
// LLVM: %[[C_VAL2:.*]] = load i32, ptr %[[C_ADDR]]
// LLVM: %[[D_VAL2:.*]] = load i32, ptr %[[D_ADDR]]
// LLVM: %[[CMP4:.*]] = icmp eq i32 %[[C_VAL2]], %[[D_VAL2]]
// LLVM: br label %[[OR_MERGE]]
// LLVM: [[OR_MERGE]]:
// LLVM: %[[OR_PHI:.*]] = phi i1 [ %[[CMP4]], %[[OR_FALSE]] ], [ true, %[[OR_TRUE]] ]
// LLVM: %[[ZEXT_OR:.*]] = zext i1 %[[OR_PHI]] to i8
// LLVM: store i8 %[[ZEXT_OR]], ptr %[[X]]
// LLVM: ret void
// OGCG-LABEL: define{{.*}} void @_Z2b3iiii(
// OGCG-SAME: i32 {{.*}} %[[ARG0:.+]], i32 {{.*}} %[[ARG1:.+]], i32 {{.*}} %[[ARG2:.+]], i32 {{.*}} %[[ARG3:.+]])
// OGCG: [[ENTRY:.*]]:
// OGCG: %[[A_ADDR:.*]] = alloca i32
// OGCG: %[[B_ADDR:.*]] = alloca i32
// OGCG: %[[C_ADDR:.*]] = alloca i32
// OGCG: %[[D_ADDR:.*]] = alloca i32
// OGCG: %[[X:.*]] = alloca i8
// OGCG: store i32 %[[ARG0]], ptr %[[A_ADDR]]
// OGCG: store i32 %[[ARG1]], ptr %[[B_ADDR]]
// OGCG: store i32 %[[ARG2]], ptr %[[C_ADDR]]
// OGCG: store i32 %[[ARG3]], ptr %[[D_ADDR]]
// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B_VAL:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[CMP1:.*]] = icmp eq i32 %[[A_VAL]], %[[B_VAL]]
// OGCG: br i1 %[[CMP1]], label %[[AND_TRUE:.+]], label %[[AND_MERGE:.+]]
// OGCG: [[AND_TRUE]]:
// OGCG: %[[C_VAL:.*]] = load i32, ptr %[[C_ADDR]]
// OGCG: %[[D_VAL:.*]] = load i32, ptr %[[D_ADDR]]
// OGCG: %[[CMP2:.*]] = icmp eq i32 %[[C_VAL]], %[[D_VAL]]
// OGCG: br label %[[AND_MERGE:.+]]
// OGCG: [[AND_MERGE]]:
// OGCG: %[[AND_PHI:.*]] = phi i1 [ false, %[[ENTRY]] ], [ %[[CMP2]], %[[AND_TRUE]] ]
// OGCG: %[[ZEXT_AND:.*]] = zext i1 %[[AND_PHI]] to i8
// OGCG: store i8 %[[ZEXT_AND]], ptr %[[X]]
// OGCG: %[[A_VAL2:.*]] = load i32, ptr %[[A_ADDR]]
// OGCG: %[[B_VAL2:.*]] = load i32, ptr %[[B_ADDR]]
// OGCG: %[[CMP3:.*]] = icmp eq i32 %[[A_VAL2]], %[[B_VAL2]]
// OGCG: br i1 %[[CMP3]], label %[[OR_MERGE:.+]], label %[[OR_FALSE:.+]]
// OGCG: [[OR_FALSE]]:
// OGCG: %[[C_VAL2:.*]] = load i32, ptr %[[C_ADDR]]
// OGCG: %[[D_VAL2:.*]] = load i32, ptr %[[D_ADDR]]
// OGCG: %[[CMP4:.*]] = icmp eq i32 %[[C_VAL2]], %[[D_VAL2]]
// OGCG: br label %[[OR_MERGE]]
// OGCG: [[OR_MERGE]]:
// OGCG: %[[OR_PHI:.*]] = phi i1 [ true, %[[AND_MERGE]] ], [ %[[CMP4]], %[[OR_FALSE]] ]
// OGCG: %[[ZEXT_OR:.*]] = zext i1 %[[OR_PHI]] to i8
// OGCG: store i8 %[[ZEXT_OR]], ptr %[[X]]
// OGCG: ret void