320 lines · cpp
1// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir2// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR3// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-llvm %s -o %t-cir.ll4// RUN: FileCheck --input-file=%t-cir.ll %s -check-prefix=LLVM5// RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll6// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG7 8void foo() {9 int a;10 int b = 1 ?: a;11}12 13// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"]14// CIR: %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]15// CIR: %[[CONST_1:.*]] = cir.const #cir.int<1> : !s32i16// CIR: cir.store{{.*}} %[[CONST_1]], %[[B_ADDR]] : !s32i, !cir.ptr<!s32i>17 18// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 419// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 420// LLVM: store i32 1, ptr %[[B_ADDR]], align 421 22// OGCG: %[[A_ADDR:.*]] = alloca i32, align 423// OGCG: %[[B_ADDR:.*]] = alloca i32, align 424// OGCG: store i32 1, ptr %[[B_ADDR]], align 425 26void foo2() {27 float _Complex a;28 float _Complex b;29 float _Complex c = a ?: b;30}31 32// CIR: %[[A_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["a"]33// CIR: %[[B_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["b"]34// CIR: %[[C_ADDR:.*]] = cir.alloca !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>, ["c", init]35// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>36// CIR: %[[A_REAL:.*]] = cir.complex.real %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float37// CIR: %[[A_IMAG:.*]] = cir.complex.imag %[[TMP_A]] : !cir.complex<!cir.float> -> !cir.float38// CIR: %[[A_REAL_BOOL:.*]] = cir.cast float_to_bool %[[A_REAL]] : !cir.float -> !cir.bool39// CIR: %[[A_IMAG_BOOL:.*]] = cir.cast float_to_bool %[[A_IMAG]] : !cir.float -> !cir.bool40// CIR: %[[CONST_TRUE:.*]] = cir.const #true41// CIR: %[[COND:.*]] = cir.select if %[[A_REAL_BOOL]] then %[[CONST_TRUE]] else %[[A_IMAG_BOOL]] : (!cir.bool, !cir.bool, !cir.bool) -> !cir.bool42// CIR: %[[RESULT:.*]] = cir.ternary(%[[COND]], true {43// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>44// CIR: cir.yield %[[TMP_A]] : !cir.complex<!cir.float>45// CIR: }, false {46// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!cir.complex<!cir.float>>, !cir.complex<!cir.float>47// CIR: cir.yield %[[TMP_B]] : !cir.complex<!cir.float>48// CIR: }) : (!cir.bool) -> !cir.complex<!cir.float>49// CIR: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !cir.complex<!cir.float>, !cir.ptr<!cir.complex<!cir.float>>50 51// LLVM: %[[A_ADDR:.*]] = alloca { float, float }, i64 1, align 452// LLVM: %[[B_ADDR:.*]] = alloca { float, float }, i64 1, align 453// LLVM: %[[C_ADDR:.*]] = alloca { float, float }, i64 1, align 454// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 455// LLVM: %[[A_REAL:.*]] = extractvalue { float, float } %[[TMP_A]], 056// LLVM: %[[A_IMAG:.*]] = extractvalue { float, float } %[[TMP_A]], 157// LLVM: %[[A_REAL_BOOL:.*]] = fcmp une float %[[A_REAL]], 0.000000e+0058// LLVM: %[[A_IMAG_BOOL:.*]] = fcmp une float %[[A_IMAG]], 0.000000e+0059// LLVM: %[[COND:.*]] = or i1 %[[A_REAL_BOOL]], %[[A_IMAG_BOOL]]60// LLVM: br i1 %[[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]61// LLVM: [[COND_TRUE]]:62// LLVM: %[[TMP_A:.*]] = load { float, float }, ptr %[[A_ADDR]], align 463// LLVM: br label %[[COND_RESULT:.*]]64// LLVM: [[COND_FALSE]]:65// LLVM: %[[TMP_B:.*]] = load { float, float }, ptr %[[B_ADDR]], align 466// LLVM: br label %[[COND_RESULT]]67// LLVM: [[COND_RESULT]]:68// LLVM: %[[RESULT:.*]] = phi { float, float } [ %[[TMP_B]], %[[COND_FALSE]] ], [ %[[TMP_A]], %[[COND_TRUE]] ]69// LLVM: br label %[[COND_END:.*]]70// LLVM: [[COND_END]]:71// LLVM: store { float, float } %[[RESULT]], ptr %[[C_ADDR]], align 472 73// OGCG: %[[A_ADDR:.*]] = alloca { float, float }, align 474// OGCG: %[[B_ADDR:.*]] = alloca { float, float }, align 475// OGCG: %[[C_ADDR:.*]] = alloca { float, float }, align 476// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 077// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 478// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 179// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 480// OGCG: %[[A_REAL_BOOL:.*]] = fcmp une float %[[A_REAL]], 0.000000e+0081// OGCG: %[[A_IMAG_BOOL:.*]] = fcmp une float %[[A_IMAG]], 0.000000e+0082// OGCG: %[[COND:.*]] = or i1 %[[A_REAL_BOOL]], %[[A_IMAG_BOOL]]83// OGCG: br i1 %tobool2, label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]84// OGCG: [[COND_TRUE]]:85// OGCG: %[[A_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 086// OGCG: %[[A_REAL:.*]] = load float, ptr %[[A_REAL_PTR]], align 487// OGCG: %[[A_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[A_ADDR]], i32 0, i32 188// OGCG: %[[A_IMAG:.*]] = load float, ptr %[[A_IMAG_PTR]], align 489// OGCG: br label %[[COND_END:.*]]90// OGCG: [[COND_FALSE]]:91// OGCG: %[[B_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 092// OGCG: %[[B_REAL:.*]] = load float, ptr %[[B_REAL_PTR]], align 493// OGCG: %[[B_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[B_ADDR]], i32 0, i32 194// OGCG: %[[B_IMAG:.*]] = load float, ptr %[[B_IMAG_PTR]], align 495// OGCG: br label %[[COND_END]]96// OGCG: [[COND_END]]:97// OGCG: %[[RESULT_REAL:.*]] = phi float [ %[[A_REAL]], %[[COND_TRUE]] ], [ %[[B_REAL]], %[[COND_FALSE]] ]98// OGCG: %[[RESULT_IMAG:.*]] = phi float [ %[[A_IMAG]], %[[COND_TRUE]] ], [ %[[B_IMAG]], %[[COND_FALSE]] ]99// OGCG: %[[C_REAL_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 0100// OGCG: %[[C_IMAG_PTR:.*]] = getelementptr inbounds nuw { float, float }, ptr %[[C_ADDR]], i32 0, i32 1101// OGCG: store float %[[RESULT_REAL]], ptr %[[C_REAL_PTR]], align 4102// OGCG: store float %[[RESULT_IMAG]], ptr %[[C_IMAG_PTR]], align 4103 104void foo3() {105 int a;106 int b;107 int c = a ?: b;108}109 110// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"]111// CIR: %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b"]112// CIR: %[[C_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init]113// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i114// CIR: %[[A_BOOL:.*]] = cir.cast int_to_bool %[[TMP_A]] : !s32i -> !cir.bool115// CIR: %[[RESULT:.*]] = cir.ternary(%[[A_BOOL]], true {116// CIR: %[[TMP_A:.*]] = cir.load{{.*}} %[[A_ADDR]] : !cir.ptr<!s32i>, !s32i117// CIR: cir.yield %[[TMP_A]] : !s32i118// CIR: }, false {119// CIR: %[[TMP_B:.*]] = cir.load{{.*}} %[[B_ADDR]] : !cir.ptr<!s32i>, !s32i120// CIR: cir.yield %[[TMP_B]] : !s32i121// CIR: }) : (!cir.bool) -> !s32i122// CIR: cir.store{{.*}} %[[RESULT]], %[[C_ADDR]] : !s32i, !cir.ptr<!s32i>123 124// LLVM: %[[A_ADDR:.*]] = alloca i32, i64 1, align 4125// LLVM: %[[B_ADDR:.*]] = alloca i32, i64 1, align 4126// LLVM: %[[C_ADDR:.*]] = alloca i32, i64 1, align 4127// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4128// LLVM: %[[COND:.*]] = icmp ne i32 %[[TMP_A]], 0129// LLVM: br i1 %[[COND]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]130// LLVM: [[COND_TRUE]]:131// LLVM: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4132// LLVM: br label %[[COND_RESULT:.*]]133// LLVM: [[COND_FALSE]]:134// LLVM: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 4135// LLVM: br label %[[COND_RESULT]]136// LLVM: [[COND_RESULT]]:137// LLVM: %[[RESULT:.*]] = phi i32 [ %[[TMP_B]], %[[COND_FALSE]] ], [ %[[TMP_A]], %[[COND_TRUE]] ]138// LLVM: br label %[[COND_END:.*]]139// LLVM: [[COND_END]]:140// LLVM: store i32 %[[RESULT]], ptr %[[C_ADDR]], align 4141 142// OGCG: %[[A_ADDR:.*]] = alloca i32, align 4143// OGCG: %[[B_ADDR:.*]] = alloca i32, align 4144// OGCG: %[[C_ADDR:.*]] = alloca i32, align 4145// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4146// OGCG: %[[A_BOOL:.*]] = icmp ne i32 %[[TMP_A]], 0147// OGCG: br i1 %[[A_BOOL]], label %[[COND_TRUE:.*]], label %[[COND_FALSE:.*]]148// OGCG: [[COND_TRUE]]:149// OGCG: %[[TMP_A:.*]] = load i32, ptr %[[A_ADDR]], align 4150// OGCG: br label %[[COND_END:.*]]151// OGCG: [[COND_FALSE]]:152// OGCG: %[[TMP_B:.*]] = load i32, ptr %[[B_ADDR]], align 4153// OGCG: br label %[[COND_END]]154// OGCG: [[COND_END]]:155// OGCG: %[[RESULT:.*]] = phi i32 [ %[[TMP_A]], %[[COND_TRUE]] ], [ %[[TMP_B]], %[[COND_FALSE]] ]156// OGCG: store i32 %[[RESULT]], ptr %[[C_ADDR]], align 4157 158void test_gnu_binary_lvalue_assign() {159 int a = 5;160 int b = 10;161 (a ?: b) = 42;162}163 164// CIR-LABEL: cir.func{{.*}} @_Z29test_gnu_binary_lvalue_assignv(165// CIR: %[[A:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]166// CIR: %[[B:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]167// CIR: %[[A_VAL:.*]] = cir.load{{.*}} %[[A]] : !cir.ptr<!s32i>, !s32i168// CIR: %[[A_BOOL:.*]] = cir.cast int_to_bool %[[A_VAL]] : !s32i -> !cir.bool169// CIR: %[[TERNARY_PTR:.*]] = cir.ternary(%[[A_BOOL]], true {170// CIR: cir.yield %[[A]] : !cir.ptr<!s32i>171// CIR: }, false {172// CIR: cir.yield %[[B]] : !cir.ptr<!s32i>173// CIR: }) : (!cir.bool) -> !cir.ptr<!s32i>174// CIR: cir.store{{.*}} %{{.*}}, %[[TERNARY_PTR]] : !s32i, !cir.ptr<!s32i>175 176// LLVM-LABEL: define{{.*}} void @_Z29test_gnu_binary_lvalue_assignv(177// LLVM: %[[A:.*]] = alloca i32178// LLVM: %[[B:.*]] = alloca i32179// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A]]180// LLVM: %[[COND:.*]] = icmp ne i32 %[[A_VAL]], 0181// LLVM: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]182// LLVM: [[TRUE_BB]]:183// LLVM: br label %[[MERGE_BB:.*]]184// LLVM: [[FALSE_BB]]:185// LLVM: br label %[[MERGE_BB]]186// LLVM: [[MERGE_BB]]:187// LLVM: %[[PHI_PTR:.*]] = phi ptr [ %[[B]], %[[FALSE_BB]] ], [ %[[A]], %[[TRUE_BB]] ]188// LLVM: br label %[[CONT_BB:.*]]189// LLVM: [[CONT_BB]]:190// LLVM: store i32 42, ptr %[[PHI_PTR]]191 192// OGCG-LABEL: define{{.*}} void @_Z29test_gnu_binary_lvalue_assignv(193// OGCG: %[[A:.*]] = alloca i32194// OGCG: %[[B:.*]] = alloca i32195// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A]]196// OGCG: %[[COND:.*]] = icmp ne i32 %[[A_VAL]], 0197// OGCG: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]198// OGCG: [[TRUE_BB]]:199// OGCG: br label %[[MERGE_BB:.*]]200// OGCG: [[FALSE_BB]]:201// OGCG: br label %[[MERGE_BB]]202// OGCG: [[MERGE_BB]]:203// OGCG: %[[PHI_PTR:.*]] = phi ptr [ %[[A]], %[[TRUE_BB]] ], [ %[[B]], %[[FALSE_BB]] ]204// OGCG: store i32 42, ptr %[[PHI_PTR]]205 206void test_gnu_binary_lvalue_compound() {207 int a = 7;208 int b = 14;209 (a ?: b) += 5;210}211 212// CIR-LABEL: cir.func{{.*}} @_Z31test_gnu_binary_lvalue_compoundv(213// CIR: %[[A:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]214// CIR: %[[B:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]215// CIR: %[[A_VAL:.*]] = cir.load{{.*}} %[[A]] : !cir.ptr<!s32i>, !s32i216// CIR: %[[A_BOOL:.*]] = cir.cast int_to_bool %[[A_VAL]] : !s32i -> !cir.bool217// CIR: %[[LVAL_PTR:.*]] = cir.ternary(%[[A_BOOL]], true {218// CIR: cir.yield %[[A]] : !cir.ptr<!s32i>219// CIR: }, false {220// CIR: cir.yield %[[B]] : !cir.ptr<!s32i>221// CIR: }) : (!cir.bool) -> !cir.ptr<!s32i>222// CIR: %[[OLD_VAL:.*]] = cir.load{{.*}} %[[LVAL_PTR]]223// CIR: %[[NEW_VAL:.*]] = cir.binop(add, %[[OLD_VAL]], %{{.*}})224// CIR: cir.store{{.*}} %[[NEW_VAL]], %[[LVAL_PTR]]225 226// LLVM-LABEL: define{{.*}} void @_Z31test_gnu_binary_lvalue_compoundv(227// LLVM: %[[A:.*]] = alloca i32228// LLVM: %[[B:.*]] = alloca i32229// LLVM: %[[A_VAL:.*]] = load i32, ptr %[[A]]230// LLVM: %[[COND:.*]] = icmp ne i32 %[[A_VAL]], 0231// LLVM: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]232// LLVM: [[TRUE_BB]]:233// LLVM: br label %[[MERGE_BB:.*]]234// LLVM: [[FALSE_BB]]:235// LLVM: br label %[[MERGE_BB]]236// LLVM: [[MERGE_BB]]:237// LLVM: %[[PTR:.*]] = phi ptr [ %[[B]], %[[FALSE_BB]] ], [ %[[A]], %[[TRUE_BB]] ]238// LLVM: br label %[[CONT:.*]]239// LLVM: [[CONT]]:240// LLVM: %[[OLD:.*]] = load i32, ptr %[[PTR]]241// LLVM: %[[NEW:.*]] = add{{.*}} i32 %[[OLD]], 5242// LLVM: store i32 %[[NEW]], ptr %[[PTR]]243 244// OGCG-LABEL: define{{.*}} void @_Z31test_gnu_binary_lvalue_compoundv(245// OGCG: %[[A:.*]] = alloca i32246// OGCG: %[[B:.*]] = alloca i32247// OGCG: %[[A_VAL:.*]] = load i32, ptr %[[A]]248// OGCG: %[[COND:.*]] = icmp ne i32 %[[A_VAL]], 0249// OGCG: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]250// OGCG: [[TRUE_BB]]:251// OGCG: br label %[[MERGE_BB:.*]]252// OGCG: [[FALSE_BB]]:253// OGCG: br label %[[MERGE_BB]]254// OGCG: [[MERGE_BB]]:255// OGCG: %[[PTR:.*]] = phi ptr [ %[[A]], %[[TRUE_BB]] ], [ %[[B]], %[[FALSE_BB]] ]256// OGCG: %[[OLD:.*]] = load i32, ptr %[[PTR]]257// OGCG: %[[NEW:.*]] = add{{.*}} i32 %[[OLD]], 5258// OGCG: store i32 %[[NEW]], ptr %[[PTR]]259 260void test_gnu_binary_lvalue_ptr() {261 int x = 1, y = 2;262 int *p = &x;263 int *q = nullptr;264 *(p ?: q) = 99;265}266 267// CIR-LABEL: cir.func{{.*}} @_Z26test_gnu_binary_lvalue_ptrv(268// CIR: %[[X:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["x", init]269// CIR: %[[Y:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["y", init]270// CIR: %[[P:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p", init]271// CIR: %[[Q:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["q", init]272// CIR: %[[P_VAL:.*]] = cir.load{{.*}} %[[P]]273// CIR: %[[P_BOOL:.*]] = cir.cast ptr_to_bool %[[P_VAL]]274// CIR: %[[PTR_RESULT:.*]] = cir.ternary(%[[P_BOOL]], true {275// CIR: %[[P_LOAD:.*]] = cir.load{{.*}} %[[P]]276// CIR: cir.yield %[[P_LOAD]] : !cir.ptr<!s32i>277// CIR: }, false {278// CIR: %[[Q_LOAD:.*]] = cir.load{{.*}} %[[Q]]279// CIR: cir.yield %[[Q_LOAD]] : !cir.ptr<!s32i>280// CIR: }) : (!cir.bool) -> !cir.ptr<!s32i>281// CIR: cir.store{{.*}} %{{.*}}, %[[PTR_RESULT]]282 283// LLVM-LABEL: define{{.*}} void @_Z26test_gnu_binary_lvalue_ptrv(284// LLVM: %[[X:.*]] = alloca i32285// LLVM: %[[Y:.*]] = alloca i32286// LLVM: %[[P:.*]] = alloca ptr287// LLVM: %[[Q:.*]] = alloca ptr288// LLVM: %[[P_VAL:.*]] = load ptr, ptr %[[P]]289// LLVM: %[[COND:.*]] = icmp ne ptr %[[P_VAL]], null290// LLVM: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]291// LLVM: [[TRUE_BB]]:292// LLVM: %[[P_LOAD:.*]] = load ptr, ptr %[[P]]293// LLVM: br label %[[MERGE_BB:.*]]294// LLVM: [[FALSE_BB]]:295// LLVM: %[[Q_LOAD:.*]] = load ptr, ptr %[[Q]]296// LLVM: br label %[[MERGE_BB]]297// LLVM: [[MERGE_BB]]:298// LLVM: %[[PHI:.*]] = phi ptr [ %[[Q_LOAD]], %[[FALSE_BB]] ], [ %[[P_LOAD]], %[[TRUE_BB]] ]299// LLVM: br label %[[CONT:.*]]300// LLVM: [[CONT]]:301// LLVM: store i32 99, ptr %[[PHI]]302 303// OGCG-LABEL: define{{.*}} void @_Z26test_gnu_binary_lvalue_ptrv(304// OGCG: %[[X:.*]] = alloca i32305// OGCG: %[[Y:.*]] = alloca i32306// OGCG: %[[P:.*]] = alloca ptr307// OGCG: %[[Q:.*]] = alloca ptr308// OGCG: %[[P_VAL:.*]] = load ptr, ptr %[[P]]309// OGCG: %[[COND:.*]] = icmp ne ptr %[[P_VAL]], null310// OGCG: br i1 %[[COND]], label %[[TRUE_BB:.*]], label %[[FALSE_BB:.*]]311// OGCG: [[TRUE_BB]]:312// OGCG: %[[P_LOAD:.*]] = load ptr, ptr %[[P]]313// OGCG: br label %[[MERGE_BB:.*]]314// OGCG: [[FALSE_BB]]:315// OGCG: %[[Q_LOAD:.*]] = load ptr, ptr %[[Q]]316// OGCG: br label %[[MERGE_BB]]317// OGCG: [[MERGE_BB]]:318// OGCG: %[[PHI:.*]] = phi ptr [ %[[P_LOAD]], %[[TRUE_BB]] ], [ %[[Q_LOAD]], %[[FALSE_BB]] ]319// OGCG: store i32 99, ptr %[[PHI]]320