From 02e18abbbd099d9d4c2d6c3fd0ad81bf61588944 Mon Sep 17 00:00:00 2001 From: Rajveer Date: Mon, 13 Jan 2025 17:21:40 +0530 Subject: [PATCH 1/2] [CIR][CIRGen] Simplify LLVM IR array initialization for clang CIR Resolves #1266 --- clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp index 526559a0060c..d7aa4326bf30 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprAgg.cpp @@ -465,14 +465,14 @@ void AggExprEmitter::emitArrayInit(Address DestPtr, cir::ArrayType AType, // Emit the explicit initializers. for (uint64_t i = 0; i != NumInitElements; ++i) { - if (i == 1) + if (i > 0) one = CGF.getBuilder().getConstInt( - loc, mlir::cast(CGF.PtrDiffTy), 1); + loc, mlir::cast(CGF.PtrDiffTy), i); // Advance to the next element. if (i > 0) { element = CGF.getBuilder().create( - loc, cirElementPtrType, element, one); + loc, cirElementPtrType, begin, one); // Tell the cleanup that it needs to destroy up to this // element. TODO: some of these stores can be trivially From 0aa5333d32e73ca2ab194293ec2bf865838a63df Mon Sep 17 00:00:00 2001 From: Rajveer Date: Tue, 14 Jan 2025 16:59:46 +0530 Subject: [PATCH 2/2] CIR: Fix regressions and add test checks for CIR / LLVM --- clang/test/CIR/CodeGen/array-init.c | 213 +++++++++++++++++++--------- 1 file changed, 148 insertions(+), 65 deletions(-) diff --git a/clang/test/CIR/CodeGen/array-init.c b/clang/test/CIR/CodeGen/array-init.c index 22c282a6ffec..19ada3a8ceb8 100644 --- a/clang/test/CIR/CodeGen/array-init.c +++ b/clang/test/CIR/CodeGen/array-init.c @@ -1,6 +1,9 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm -fno-clangir-call-conv-lowering %s -o %t.ll +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s -// CHECK-DAG: cir.global "private" constant cir_private @__const.foo.bar = #cir.const_array<[#cir.fp<9.000000e+00> : !cir.double, #cir.fp<8.000000e+00> : !cir.double, #cir.fp<7.000000e+00> : !cir.double]> : !cir.array +// CIR-DAG: cir.global "private" constant cir_private @__const.foo.bar = #cir.const_array<[#cir.fp<9.000000e+00> : !cir.double, #cir.fp<8.000000e+00> : !cir.double, #cir.fp<7.000000e+00> : !cir.double]> : !cir.array typedef struct { int a; long b; @@ -9,78 +12,158 @@ typedef struct { void buz(int x) { T arr[] = { {0, x}, {0, 0} }; } -// CHECK: cir.func @buz -// CHECK-NEXT: [[X_ALLOCA:%.*]] = cir.alloca !s32i, !cir.ptr, ["x", init] {alignment = 4 : i64} -// CHECK-NEXT: [[ARR:%.*]] = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 16 : i64} -// CHECK-NEXT: cir.store %arg0, [[X_ALLOCA]] : !s32i, !cir.ptr -// CHECK-NEXT: [[ARR_INIT:%.*]] = cir.const #cir.zero : !cir.array -// CHECK-NEXT: cir.store [[ARR_INIT]], [[ARR]] : !cir.array, !cir.ptr> -// CHECK-NEXT: [[FI_EL:%.*]] = cir.cast(array_to_ptrdecay, [[ARR]] : !cir.ptr>), !cir.ptr -// CHECK-NEXT: [[A_STORAGE0:%.*]] = cir.get_member [[FI_EL]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CHECK-NEXT: [[B_STORAGE0:%.*]] = cir.get_member [[FI_EL]][1] {name = "b"} : !cir.ptr -> !cir.ptr -// CHECK-NEXT: [[X_VAL:%.*]] = cir.load [[X_ALLOCA]] : !cir.ptr, !s32i -// CHECK-NEXT: [[X_CASTED:%.*]] = cir.cast(integral, [[X_VAL]] : !s32i), !s64i -// CHECK-NEXT: cir.store [[X_CASTED]], [[B_STORAGE0]] : !s64i, !cir.ptr -// CHECK-NEXT: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i -// CHECK-NEXT: [[SE_EL:%.*]] = cir.ptr_stride([[FI_EL]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr -// CHECK-NEXT: [[A_STORAGE1:%.*]] = cir.get_member [[SE_EL]][0] {name = "a"} : !cir.ptr -> !cir.ptr -// CHECK-NEXT: [[B_STORAGE1:%.*]] = cir.get_member [[SE_EL]][1] {name = "b"} : !cir.ptr -> !cir.ptr -// CHECK-NEXT: cir.return +// CIR: cir.func @buz +// CIR-NEXT: [[X_ALLOCA:%.*]] = cir.alloca !s32i, !cir.ptr, ["x", init] {alignment = 4 : i64} +// CIR-NEXT: [[ARR:%.*]] = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 16 : i64} +// CIR-NEXT: cir.store %arg0, [[X_ALLOCA]] : !s32i, !cir.ptr +// CIR-NEXT: [[ARR_INIT:%.*]] = cir.const #cir.zero : !cir.array +// CIR-NEXT: cir.store [[ARR_INIT]], [[ARR]] : !cir.array, !cir.ptr> +// CIR-NEXT: [[FI_EL:%.*]] = cir.cast(array_to_ptrdecay, [[ARR]] : !cir.ptr>), !cir.ptr +// CIR-NEXT: [[A_STORAGE0:%.*]] = cir.get_member [[FI_EL]][0] {name = "a"} : !cir.ptr -> !cir.ptr +// CIR-NEXT: [[B_STORAGE0:%.*]] = cir.get_member [[FI_EL]][1] {name = "b"} : !cir.ptr -> !cir.ptr +// CIR-NEXT: [[X_VAL:%.*]] = cir.load [[X_ALLOCA]] : !cir.ptr, !s32i +// CIR-NEXT: [[X_CASTED:%.*]] = cir.cast(integral, [[X_VAL]] : !s32i), !s64i +// CIR-NEXT: cir.store [[X_CASTED]], [[B_STORAGE0]] : !s64i, !cir.ptr +// CIR-NEXT: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR-NEXT: [[SE_EL:%.*]] = cir.ptr_stride([[FI_EL]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR-NEXT: [[A_STORAGE1:%.*]] = cir.get_member [[SE_EL]][0] {name = "a"} : !cir.ptr -> !cir.ptr +// CIR-NEXT: [[B_STORAGE1:%.*]] = cir.get_member [[SE_EL]][1] {name = "b"} : !cir.ptr -> !cir.ptr +// CIR-NEXT: cir.return void foo() { double bar[] = {9,8,7}; } -// CHECK-LABEL: @foo -// CHECK: %[[DST:.*]] = cir.alloca !cir.array, !cir.ptr>, ["bar"] -// CHECK: %[[SRC:.*]] = cir.get_global @__const.foo.bar : !cir.ptr> -// CHECK: cir.copy %[[SRC]] to %[[DST]] : !cir.ptr> +// CIR-LABEL: @foo +// CIR: %[[DST:.*]] = cir.alloca !cir.array, !cir.ptr>, ["bar"] +// CIR: %[[SRC:.*]] = cir.get_global @__const.foo.bar : !cir.ptr> +// CIR: cir.copy %[[SRC]] to %[[DST]] : !cir.ptr> void bar(int a, int b, int c) { int arr[] = {a,b,c}; } -// CHECK: cir.func @bar -// CHECK: [[ARR:%.*]] = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 4 : i64} -// CHECK-NEXT: cir.store %arg0, [[A:%.*]] : !s32i, !cir.ptr -// CHECK-NEXT: cir.store %arg1, [[B:%.*]] : !s32i, !cir.ptr -// CHECK-NEXT: cir.store %arg2, [[C:%.*]] : !s32i, !cir.ptr -// CHECK-NEXT: [[FI_EL:%.*]] = cir.cast(array_to_ptrdecay, [[ARR]] : !cir.ptr>), !cir.ptr -// CHECK-NEXT: [[LOAD_A:%.*]] = cir.load [[A]] : !cir.ptr, !s32i -// CHECK-NEXT: cir.store [[LOAD_A]], [[FI_EL]] : !s32i, !cir.ptr -// CHECK-NEXT: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i -// CHECK-NEXT: [[SE_EL:%.*]] = cir.ptr_stride(%4 : !cir.ptr, [[ONE]] : !s64i), !cir.ptr -// CHECK-NEXT: [[LOAD_B:%.*]] = cir.load [[B]] : !cir.ptr, !s32i -// CHECK-NEXT: cir.store [[LOAD_B]], [[SE_EL]] : !s32i, !cir.ptr -// CHECK-NEXT: [[TH_EL:%.*]] = cir.ptr_stride(%7 : !cir.ptr, [[ONE]] : !s64i), !cir.ptr -// CHECK-NEXT: [[LOAD_C:%.*]] = cir.load [[C]] : !cir.ptr, !s32i -// CHECK-NEXT: cir.store [[LOAD_C]], [[TH_EL]] : !s32i, !cir.ptr +// CIR: cir.func @bar +// CIR: [[ARR:%.*]] = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 4 : i64} +// CIR-NEXT: cir.store %arg0, [[A:%.*]] : !s32i, !cir.ptr +// CIR-NEXT: cir.store %arg1, [[B:%.*]] : !s32i, !cir.ptr +// CIR-NEXT: cir.store %arg2, [[C:%.*]] : !s32i, !cir.ptr +// CIR-NEXT: [[FI_EL:%.*]] = cir.cast(array_to_ptrdecay, [[ARR]] : !cir.ptr>), !cir.ptr +// CIR-NEXT: [[LOAD_A:%.*]] = cir.load [[A]] : !cir.ptr, !s32i +// CIR-NEXT: cir.store [[LOAD_A]], [[FI_EL]] : !s32i, !cir.ptr +// CIR-NEXT: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR-NEXT: [[SE_EL:%.*]] = cir.ptr_stride(%4 : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR-NEXT: [[LOAD_B:%.*]] = cir.load [[B]] : !cir.ptr, !s32i +// CIR-NEXT: cir.store [[LOAD_B]], [[SE_EL]] : !s32i, !cir.ptr +// CIR-NEXT: [[TWO:%.*]] = cir.const #cir.int<2> : !s64i +// CIR-NEXT: [[TH_EL:%.*]] = cir.ptr_stride(%4 : !cir.ptr, [[TWO]] : !s64i), !cir.ptr +// CIR-NEXT: [[LOAD_C:%.*]] = cir.load [[C]] : !cir.ptr, !s32i +// CIR-NEXT: cir.store [[LOAD_C]], [[TH_EL]] : !s32i, !cir.ptr void zero_init(int x) { int arr[3] = {x}; } -// CHECK: cir.func @zero_init -// CHECK: [[VAR_ALLOC:%.*]] = cir.alloca !s32i, !cir.ptr, ["x", init] {alignment = 4 : i64} -// CHECK: %1 = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 4 : i64} -// CHECK: [[TEMP:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["arrayinit.temp", init] {alignment = 8 : i64} -// CHECK: cir.store %arg0, [[VAR_ALLOC]] : !s32i, !cir.ptr -// CHECK: [[BEGIN:%.*]] = cir.cast(array_to_ptrdecay, %1 : !cir.ptr>), !cir.ptr -// CHECK: [[VAR:%.*]] = cir.load [[VAR_ALLOC]] : !cir.ptr, !s32i -// CHECK: cir.store [[VAR]], [[BEGIN]] : !s32i, !cir.ptr -// CHECK: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i -// CHECK: [[ZERO_INIT_START:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr -// CHECK: cir.store [[ZERO_INIT_START]], [[TEMP]] : !cir.ptr, !cir.ptr> -// CHECK: [[SIZE:%.*]] = cir.const #cir.int<3> : !s64i -// CHECK: [[END:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[SIZE]] : !s64i), !cir.ptr -// CHECK: cir.do { -// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr -// CHECK: [[FILLER:%.*]] = cir.const #cir.int<0> : !s32i -// CHECK: cir.store [[FILLER]], [[CUR]] : !s32i, !cir.ptr -// CHECK: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i -// CHECK: [[NEXT:%.*]] = cir.ptr_stride([[CUR]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr -// CHECK: cir.store [[NEXT]], [[TEMP]] : !cir.ptr, !cir.ptr> -// CHECK: cir.yield -// CHECK: } while { -// CHECK: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr -// CHECK: [[CMP:%.*]] = cir.cmp(ne, [[CUR]], [[END]]) : !cir.ptr, !cir.bool -// CHECK: cir.condition([[CMP]]) -// CHECK: } -// CHECK: cir.return +// CIR: cir.func @zero_init +// CIR: [[VAR_ALLOC:%.*]] = cir.alloca !s32i, !cir.ptr, ["x", init] {alignment = 4 : i64} +// CIR: %1 = cir.alloca !cir.array, !cir.ptr>, ["arr", init] {alignment = 4 : i64} +// CIR: [[TEMP:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["arrayinit.temp", init] {alignment = 8 : i64} +// CIR: cir.store %arg0, [[VAR_ALLOC]] : !s32i, !cir.ptr +// CIR: [[BEGIN:%.*]] = cir.cast(array_to_ptrdecay, %1 : !cir.ptr>), !cir.ptr +// CIR: [[VAR:%.*]] = cir.load [[VAR_ALLOC]] : !cir.ptr, !s32i +// CIR: cir.store [[VAR]], [[BEGIN]] : !s32i, !cir.ptr +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR: [[ZERO_INIT_START:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR: cir.store [[ZERO_INIT_START]], [[TEMP]] : !cir.ptr, !cir.ptr> +// CIR: [[SIZE:%.*]] = cir.const #cir.int<3> : !s64i +// CIR: [[END:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[SIZE]] : !s64i), !cir.ptr +// CIR: cir.do { +// CIR: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr +// CIR: [[FILLER:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store [[FILLER]], [[CUR]] : !s32i, !cir.ptr +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR: [[NEXT:%.*]] = cir.ptr_stride([[CUR]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR: cir.store [[NEXT]], [[TEMP]] : !cir.ptr, !cir.ptr> +// CIR: cir.yield +// CIR: } while { +// CIR: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr +// CIR: [[CMP:%.*]] = cir.cmp(ne, [[CUR]], [[END]]) : !cir.ptr, !cir.bool +// CIR: cir.condition([[CMP]]) +// CIR: } +// CIR: cir.return + +void aggr_init() { + int g = 5; + int g_arr[5] = {1, 2, 3, g}; +} +// CIR-LABEL: cir.func no_proto @aggr_init +// CIR: [[VAR_ALLOC:%.*]] = cir.alloca !s32i, !cir.ptr, ["g", init] {alignment = 4 : i64} +// CIR: %1 = cir.alloca !cir.array, !cir.ptr>, ["g_arr", init] {alignment = 16 : i64} +// CIR: [[TEMP:%.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["arrayinit.temp", init] {alignment = 8 : i64} +// CIR: %3 = cir.const #cir.int<5> : !s32i +// CIR: cir.store %3, [[VAR_ALLOC]] : !s32i, !cir.ptr +// CIR: [[BEGIN:%.*]] = cir.cast(array_to_ptrdecay, %1 : !cir.ptr>), !cir.ptr +// CIR: %5 = cir.const #cir.int<1> : !s32i +// CIR: cir.store %5, [[BEGIN]] : !s32i, !cir.ptr +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR: %7 = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR: %8 = cir.const #cir.int<2> : !s32i +// CIR: cir.store %8, %7 : !s32i, !cir.ptr +// CIR: [[TWO:%.*]] = cir.const #cir.int<2> : !s64i +// CIR: %10 = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[TWO]] : !s64i), !cir.ptr +// CIR: %11 = cir.const #cir.int<3> : !s32i +// CIR: cir.store %11, %10 : !s32i, !cir.ptr +// CIR: [[THREE:%.*]] = cir.const #cir.int<3> : !s64i +// CIR: %13 = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[THREE]] : !s64i), !cir.ptr +// CIR: [[VAR:%.*]] = cir.load [[VAR_ALLOC]] : !cir.ptr, !s32i +// CIR: cir.store [[VAR]], %13 : !s32i, !cir.ptr +// CIR: [[ONE_VAR:%.*]] = cir.const #cir.int<1> : !s64i +// CIR: %16 = cir.ptr_stride(%13 : !cir.ptr, [[ONE_VAR]] : !s64i), !cir.ptr +// CIR: cir.store %16, [[TEMP]] : !cir.ptr, !cir.ptr> +// CIR: [[SIZE:%.*]] = cir.const #cir.int<5> : !s64i +// CIR: [[END:%.*]] = cir.ptr_stride([[BEGIN]] : !cir.ptr, [[SIZE]] : !s64i), !cir.ptr +// CIR: cir.do { +// CIR: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr +// CIR: [[FILLER:%.*]] = cir.const #cir.int<0> : !s32i +// CIR: cir.store [[FILLER]], [[CUR]] : !s32i, !cir.ptr +// CIR: [[ONE:%.*]] = cir.const #cir.int<1> : !s64i +// CIR: [[NEXT:%.*]] = cir.ptr_stride([[CUR]] : !cir.ptr, [[ONE]] : !s64i), !cir.ptr +// CIR: cir.store [[NEXT]], [[TEMP]] : !cir.ptr, !cir.ptr> +// CIR: cir.yield +// CIR: } while { +// CIR: [[CUR:%.*]] = cir.load [[TEMP]] : !cir.ptr>, !cir.ptr +// CIR: [[CMP:%.*]] = cir.cmp(ne, [[CUR]], [[END]]) : !cir.ptr, !cir.bool +// CIR: cir.condition([[CMP]]) +// CIR: } +// CIR: cir.return +// +// LLVM-LABEL: @aggr_init +// LLVM: [[VAR_ALLOC:%.*]] = alloca i32, i64 1, align 4 +// LLVM: %2 = alloca [5 x i32], i64 1, align 16 +// LLVM: [[TEMP:%.*]] = alloca ptr, i64 1, align 8 +// LLVM: store i32 5, ptr [[VAR_ALLOC]], align 4 +// LLVM: [[BEGIN:%.*]] = getelementptr i32, ptr %2, i32 0 +// LLVM: store i32 1, ptr [[BEGIN]], align 4 +// LLVM: [[ONE:%.*]] = getelementptr i32, ptr [[BEGIN]], i64 1 +// LLVM: store i32 2, ptr [[ONE]], align 4 +// LLVM: [[TWO:%.*]] = getelementptr i32, ptr [[BEGIN]], i64 2 +// LLVM: store i32 3, ptr [[TWO]], align 4 +// LLVM: [[THREE:%.*]] = getelementptr i32, ptr [[BEGIN]], i64 3 +// LLVM: [[VAR:%.*]] = load i32, ptr [[VAR_ALLOC]], align 4 +// LLVM: store i32 [[VAR]], ptr [[THREE]], align 4 +// LLVM: %9 = getelementptr i32, ptr [[THREE]], i64 1 +// LLVM: store ptr %9, ptr [[TEMP]], align 8 +// LLVM: [[END:%.*]] = getelementptr i32, ptr [[BEGIN]], i64 5 +// LLVM: br label %14 +// +// LLVM: 11: ; preds = %14 +// LLVM: [[CUR:%.*]] = load ptr, ptr [[TEMP]], align 8 +// LLVM: [[CMP:%.*]] = icmp ne ptr [[CUR]], [[END]] +// LLVM: br i1 [[CMP]], label %14, label %17 +// +// LLVM: 14: ; preds = %11, %0 +// LLVM: [[CUR:%.*]] = load ptr, ptr [[TEMP]], align 8 +// LLVM: store i32 0, ptr [[CUR]], align 4 +// LLVM: [[NEXT:%.*]] = getelementptr i32, ptr [[CUR]], i64 1 +// LLVM: store ptr [[NEXT]], ptr [[TEMP]], align 8 +// LLVM: br label %11 +// +// LLVM: 17: ; preds = %11 +// LLVM: ret void