326 lines · c
1// RUN: %clang_cc1 -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 -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 -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 8enum A {9 A_one,10 A_two11};12enum A a;13 14// CHECK: cir.global external @a = #cir.int<0> : !u32i15 16enum B : int;17enum B b;18 19// CHECK: cir.global external @b = #cir.int<0> : !u32i20 21 22enum C : int {23 C_one,24 C_two25};26enum C c;27 28// CHECK: cir.global external @c = #cir.int<0> : !u32i29 30int f1(int i);31 32int f1(int i) {33 i;34 return i;35}36 37// CIR: cir.func{{.*}} @f1(%arg0: !s32i loc({{.*}})) -> !s32i38// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}39// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}40// CIR-NEXT: cir.store{{.*}} %arg0, %[[I_PTR]] : !s32i, !cir.ptr<!s32i>41// CIR-NEXT: %[[I_IGNORED:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i42// CIR-NEXT: %[[I:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i43// CIR-NEXT: cir.store{{.*}} %[[I]], %[[RV]] : !s32i, !cir.ptr<!s32i>44// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i45// CIR-NEXT: cir.return %[[R]] : !s32i46 47// LLVM: define{{.*}} i32 @f1(i32 %[[IP:.*]])48// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 449// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 450// LLVM-NEXT: store i32 %[[IP]], ptr %[[I_PTR]], align 451// LLVM-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 452// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 453// LLVM-NEXT: store i32 %[[I]], ptr %[[RV]], align 454// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 455// LLVM-NEXT: ret i32 %[[R]]56 57// OGCG: define{{.*}} i32 @f1(i32 noundef %[[I:.*]])58// OGCG-NEXT: entry:59// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 460// OGCG-NEXT: store i32 %[[I]], ptr %[[I_PTR]], align 461// OGCG-NEXT: %[[I_IGNORED:.*]] = load i32, ptr %[[I_PTR]], align 462// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 463// OGCG-NEXT: ret i32 %[[I]]64 65int f2(void) { return 3; }66 67// CIR: cir.func{{.*}} @f2() -> !s32i68// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}69// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i70// CIR-NEXT: cir.store{{.*}} %[[THREE]], %[[RV]] : !s32i, !cir.ptr<!s32i>71// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %0 : !cir.ptr<!s32i>, !s32i72// CIR-NEXT: cir.return %[[R]] : !s32i73 74// LLVM: define{{.*}} i32 @f2()75// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 476// LLVM-NEXT: store i32 3, ptr %[[RV]], align 477// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 478// LLVM-NEXT: ret i32 %[[R]]79 80// OGCG: define{{.*}} i32 @f2()81// OGCG-NEXT: entry:82// OGCG-NEXT: ret i32 383 84int f3(void) {85 int i = 3;86 return i;87}88 89// CIR: cir.func{{.*}} @f3() -> !s32i90// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}91// CIR-NEXT: %[[I_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["i", init] {alignment = 4 : i64}92// CIR-NEXT: %[[THREE:.*]] = cir.const #cir.int<3> : !s32i93// CIR-NEXT: cir.store{{.*}} %[[THREE]], %[[I_PTR]] : !s32i, !cir.ptr<!s32i>94// CIR-NEXT: %[[I:.*]] = cir.load{{.*}} %[[I_PTR]] : !cir.ptr<!s32i>, !s32i95// CIR-NEXT: cir.store{{.*}} %[[I]], %[[RV]] : !s32i, !cir.ptr<!s32i>96// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i97// CIR-NEXT: cir.return %[[R]] : !s32i98 99// LLVM: define{{.*}} i32 @f3()100// LLVM-NEXT: %[[RV:.*]] = alloca i32, i64 1, align 4101// LLVM-NEXT: %[[I_PTR:.*]] = alloca i32, i64 1, align 4102// LLVM-NEXT: store i32 3, ptr %[[I_PTR]], align 4103// LLVM-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4104// LLVM-NEXT: store i32 %[[I]], ptr %[[RV]], align 4105// LLVM-NEXT: %[[R:.*]] = load i32, ptr %[[RV]], align 4106// LLVM-NEXT: ret i32 %[[R]]107 108// OGCG: define{{.*}} i32 @f3109// OGCG-NEXT: entry:110// OGCG-NEXT: %[[I_PTR:.*]] = alloca i32, align 4111// OGCG-NEXT: store i32 3, ptr %[[I_PTR]], align 4112// OGCG-NEXT: %[[I:.*]] = load i32, ptr %[[I_PTR]], align 4113// OGCG-NEXT: ret i32 %[[I]]114 115// Verify null statement handling.116void f4(void) {117 ;118}119 120// CIR: cir.func{{.*}} @f4()121// CIR-NEXT: cir.return122 123// LLVM: define{{.*}} void @f4()124// LLVM-NEXT: ret void125 126// OGCG: define{{.*}} void @f4()127// OGCG-NEXT: entry:128// OGCG-NEXT: ret void129 130// Verify null statement as for-loop body.131void f5(void) {132 for (;;)133 ;134}135 136// CIR: cir.func{{.*}} @f5()137// CIR-NEXT: cir.scope {138// CIR-NEXT: cir.for : cond {139// CIR-NEXT: %0 = cir.const #true140// CIR-NEXT: cir.condition(%0)141// CIR-NEXT: } body {142// CIR-NEXT: cir.yield143// CIR-NEXT: } step {144// CIR-NEXT: cir.yield145// CIR-NEXT: }146// CIR-NEXT: }147// CIR-NEXT: cir.return148// CIR-NEXT: }149 150// LLVM: define{{.*}} void @f5()151// LLVM: br label %[[SCOPE:.*]]152// LLVM: [[SCOPE]]:153// LLVM: br label %[[LOOP:.*]]154// LLVM: [[LOOP]]:155// LLVM: br i1 true, label %[[LOOP_STEP:.*]], label %[[LOOP_EXIT:.*]]156// LLVM: [[LOOP_STEP]]:157// LLVM: br label %[[LOOP_BODY:.*]]158// LLVM: [[LOOP_BODY]]:159// LLVM: br label %[[LOOP]]160// LLVM: [[LOOP_EXIT]]:161// LLVM: ret void162 163// OGCG: define{{.*}} void @f5()164// OGCG: entry:165// OGCG: br label %[[LOOP:.*]]166// OGCG: [[LOOP]]:167// OGCG: br label %[[LOOP]]168 169int gv;170int f6(void) {171 return gv;172}173 174// CIR: cir.func{{.*}} @f6() -> !s32i175// CIR-NEXT: %[[RV:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"] {alignment = 4 : i64}176// CIR-NEXT: %[[GV_PTR:.*]] = cir.get_global @gv : !cir.ptr<!s32i>177// CIR-NEXT: %[[GV:.*]] = cir.load{{.*}} %[[GV_PTR]] : !cir.ptr<!s32i>, !s32i178// CIR-NEXT: cir.store{{.*}} %[[GV]], %[[RV]] : !s32i, !cir.ptr<!s32i>179// CIR-NEXT: %[[R:.*]] = cir.load{{.*}} %[[RV]] : !cir.ptr<!s32i>, !s32i180// CIR-NEXT: cir.return %[[R]] : !s32i181 182// LLVM: define{{.*}} i32 @f6()183// LLVM-NEXT: %[[RV_PTR:.*]] = alloca i32, i64 1, align 4184// LLVM-NEXT: %[[GV:.*]] = load i32, ptr @gv, align 4185// LLVM-NEXT: store i32 %[[GV]], ptr %[[RV_PTR]], align 4186// LLVM-NEXT: %[[RV:.*]] = load i32, ptr %[[RV_PTR]], align 4187// LLVM-NEXT: ret i32 %[[RV]]188 189// OGCG: define{{.*}} i32 @f6()190// OGCG-NEXT: entry:191// OGCG-NEXT: %[[GV:.*]] = load i32, ptr @gv, align 4192// OGCG-NEXT: ret i32 %[[GV]]193 194int f7(int a, int b, int c) {195 return a + (b + c);196}197 198// CIR: cir.func{{.*}} @f7199// CIR: %[[A_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a", init]200// CIR: %[[B_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b", init]201// CIR: %[[C_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["c", init]202// CIR: %[[A:.*]] = cir.load{{.*}} %[[A_PTR]] : !cir.ptr<!s32i>, !s32i203// CIR: %[[B:.*]] = cir.load{{.*}} %[[B_PTR]] : !cir.ptr<!s32i>, !s32i204// CIR: %[[C:.*]] = cir.load{{.*}} %[[C_PTR]] : !cir.ptr<!s32i>, !s32i205// CIR: %[[B_PLUS_C:.*]] = cir.binop(add, %[[B]], %[[C]]) nsw : !s32i206// CIR: %[[RETVAL:.*]] = cir.binop(add, %[[A]], %[[B_PLUS_C]]) nsw : !s32i207 208// LLVM: define{{.*}} i32 @f7209// LLVM: %[[A_PTR:.*]] = alloca i32, i64 1, align 4210// LLVM: %[[B_PTR:.*]] = alloca i32, i64 1, align 4211// LLVM: %[[C_PTR:.*]] = alloca i32, i64 1, align 4212// LLVM: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4213// LLVM: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4214// LLVM: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4215// LLVM: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]216// LLVM: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]217 218// OGCG: define{{.*}} i32 @f7219// OGCG: entry:220// OGCG: %[[A_PTR:.*]] = alloca i32, align 4221// OGCG: %[[B_PTR:.*]] = alloca i32, align 4222// OGCG: %[[C_PTR:.*]] = alloca i32, align 4223// OGCG: %[[A:.*]] = load i32, ptr %[[A_PTR]], align 4224// OGCG: %[[B:.*]] = load i32, ptr %[[B_PTR]], align 4225// OGCG: %[[C:.*]] = load i32, ptr %[[C_PTR]], align 4226// OGCG: %[[B_PLUS_C:.*]] = add nsw i32 %[[B]], %[[C]]227// OGCG: %[[RETVAL:.*]] = add nsw i32 %[[A]], %[[B_PLUS_C]]228 229int f8(int *p) {230 (*p) = 2;231 return (*p);232}233 234// CIR: cir.func{{.*}} @f8235// CIR: %[[P_PTR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["p", init]236// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i237// CIR: %[[P:.*]] = cir.load deref{{.*}} %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>238// CIR: cir.store{{.*}} %[[TWO]], %[[P]] : !s32i, !cir.ptr<!s32i>239// CIR: %[[P2:.*]] = cir.load deref{{.*}} %[[P_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>240// CIR: %[[STAR_P:.*]] = cir.load{{.*}} %[[P2]] : !cir.ptr<!s32i>, !s32i241 242// LLVM: define{{.*}} i32 @f8243// LLVM: %[[P_PTR:.*]] = alloca ptr, i64 1, align 8244// LLVM: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8245// LLVM: store i32 2, ptr %[[P]], align 4246// LLVM: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8247// LLVM: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4248 249// OGCG: define{{.*}} i32 @f8250// OGCG: entry:251// OGCG: %[[P_PTR:.*]] = alloca ptr, align 8252// OGCG: %[[P:.*]] = load ptr, ptr %[[P_PTR]], align 8253// OGCG: store i32 2, ptr %[[P]], align 4254// OGCG: %[[P2:.*]] = load ptr, ptr %[[P_PTR]], align 8255// OGCG: %[[STAR_P:.*]] = load i32, ptr %[[P2]], align 4256 257 258void f9() {}259 260// CIR: cir.func{{.*}} @f9()261// CIR-NEXT: cir.return262 263// LLVM: define{{.*}} void @f9()264// LLVM-NEXT: ret void265 266// OGCG: define{{.*}} void @f9()267// OGCG-NEXT: entry:268// OGCG-NEXT: ret void269 270void f10(int arg0, ...) {}271 272// CIR: cir.func{{.*}} @f10(%[[ARG0:.*]]: !s32i loc({{.*}}), ...)273// CIR-NEXT: %[[ARG0_PTR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["arg0", init] {alignment = 4 : i64}274// CIR-NEXT: cir.store{{.*}} %[[ARG0]], %[[ARG0_PTR]] : !s32i, !cir.ptr<!s32i>275// CIR-NEXT: cir.return276 277// LLVM: define{{.*}} void @f10(i32 %[[ARG0:.*]], ...)278// LLVM-NEXT: %[[ARG0_PTR:.*]] = alloca i32, i64 1, align 4279// LLVM-NEXT: store i32 %[[ARG0]], ptr %[[ARG0_PTR]], align 4280// LLVM-NEXT: ret void281 282// OGCG: define{{.*}} void @f10(i32 noundef %[[ARG0:.*]], ...)283// OGCG-NEXT: entry:284// OGCG-NEXT: %[[ARG0_PTR:.*]] = alloca i32, align 4285// OGCG-NEXT: store i32 %[[ARG0]], ptr %[[ARG0_PTR]], align 4286// OGCG-NEXT: ret void287 288typedef unsigned long size_type;289typedef unsigned long _Tp;290 291size_type max_size(void) {292 return (size_type)~0 / sizeof(_Tp);293}294 295// CIR: cir.func{{.*}} @max_size()296// CIR: %0 = cir.alloca !u64i, !cir.ptr<!u64i>, ["__retval"] {alignment = 8 : i64}297// CIR: %1 = cir.const #cir.int<0> : !s32i298// CIR: %2 = cir.unary(not, %1) : !s32i, !s32i299// CIR: %3 = cir.cast integral %2 : !s32i -> !u64i300// CIR: %4 = cir.const #cir.int<8> : !u64i301// CIR: %5 = cir.binop(div, %3, %4) : !u64i302 303// LLVM: define{{.*}} i64 @max_size()304// LLVM: store i64 2305843009213693951, ptr305 306// OGCG: define{{.*}} i64 @max_size()307// OGCG: ret i64 2305843009213693951308// CHECK: cir.store{{.*}} %5, %0 : !u64i, !cir.ptr<!u64i>309// CHECK: %6 = cir.load{{.*}} %0 : !cir.ptr<!u64i>, !u64i310// CHECK: cir.return %6 : !u64i311// CHECK: }312 313void test_char_literal() {314 char c;315 c = 'X';316}317 318// CIR: cir.func{{.*}} @test_char_literal319// CIR: cir.const #cir.int<88>320 321// LLVM: define{{.*}} void @test_char_literal()322// LLVM: store i8 88, ptr %{{.*}}, align 1323 324// OGCG: define{{.*}} void @test_char_literal()325// OGCG: store i8 88, ptr %{{.*}}, align 1326