From 6d83bdc82c0c59dbe28f158fd207405709b48d17 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Mon, 31 Oct 2022 17:54:37 +0800 Subject: [PATCH] [opaque pointers][flang2] Remove redundant bitcast instructions and rewrite typed pointer with 'ptr'. 1. In the function 'make_bitcast()', a copy of the source with the type of the dest is returned when both the data types of source and dest are LL_PTR. 2. Due to the above modification, in function 'make_load()', flang should always get the load type from ll_type in the operand. 3. Remove the bitcast instruction used to store different types of results to the address of the return variable when processing ENTRY statements. 4. For some hard-coded typed pointers in code blocks controlled by conditional compilation macros, rewrite them with 'ptr'. --- test/directives/getarg.f90 | 4 +- test/directives/prefetch.f90 | 4 +- test/llvm_ir_correct/save.f90 | 3 +- tools/flang2/flang2exe/cgmain.cpp | 86 +++++------------------ tools/flang2/flang2exe/ll_ftn.cpp | 49 +++---------- tools/flang2/flang2exe/ll_write.cpp | 58 +++++---------- tools/flang2/flang2exe/llassem_common.cpp | 4 +- 7 files changed, 54 insertions(+), 154 deletions(-) diff --git a/test/directives/getarg.f90 b/test/directives/getarg.f90 index f8530b420eb6..ca28ee0809da 100644 --- a/test/directives/getarg.f90 +++ b/test/directives/getarg.f90 @@ -8,5 +8,5 @@ subroutine test() call getarg(pos, arg) end subroutine -! CHECK: bitcast ptr @f90_getarga to ptr, -! CHECK-NOT: bitcast ptr @getarg_ to ptr, +! CHECK: call void {{.*}}@f90_getarga(ptr {{.*}}, ptr {{.*}}, ptr {{.*}}, i64{{.*}}), +! CHECK-NOT: call void {{.*}}@getarg_(i8 {{.*}}, i8 {{.*}}, i64{{.*}}), diff --git a/test/directives/prefetch.f90 b/test/directives/prefetch.f90 index c5f84a70a506..48f66538d6f8 100644 --- a/test/directives/prefetch.f90 +++ b/test/directives/prefetch.f90 @@ -12,9 +12,7 @@ subroutine prefetch_dir(a1, a2) end subroutine prefetch_dir !! Ensure that the offset generated for the prefetch of a2(i + 256) is correct. -! CHECK-PREFETCH: [[a1:%[0-9]+]] = bitcast ptr %a1 to ptr -! CHECK-PREFETCH: [[a2:%[0-9]+]] = bitcast ptr %a2 to ptr -! CHECK-PREFETCH: [[a2base:%[0-9]+]] = getelementptr i8, ptr [[a2]], i64 1020 +! CHECK-PREFETCH: [[a2base:%[0-9]+]] = getelementptr i8, ptr %a2, i64 1020 ! CHECK-PREFETCH: [[i:%[0-9]+]] = load i32 ! CHECK-PREFETCH: [[TMP1:%[0-9]+]] = sext i32 [[i]] to i64 ! CHECK-PREFETCH: [[TMP2:%[0-9]+]] = mul nsw i64 [[TMP1]], 4 diff --git a/test/llvm_ir_correct/save.f90 b/test/llvm_ir_correct/save.f90 index 7206fa5a6b55..a38447ad3939 100644 --- a/test/llvm_ir_correct/save.f90 +++ b/test/llvm_ir_correct/save.f90 @@ -15,8 +15,7 @@ program msave ! NOSAVE: alloca i32 integer :: x ! NOSAVE: store i32 5, ptr %x -! SAVE: bitcast ptr @.BSS1 to ptr -! SAVE: store i32 5, ptr +! SAVE: store i32 5, ptr @.BSS1 x = 5 end program diff --git a/tools/flang2/flang2exe/cgmain.cpp b/tools/flang2/flang2exe/cgmain.cpp index f01d6adacde0..82032eec8026 100644 --- a/tools/flang2/flang2exe/cgmain.cpp +++ b/tools/flang2/flang2exe/cgmain.cpp @@ -4372,7 +4372,7 @@ gen_va_start(int ilix) if (!va_start_defined) { va_start_defined = true; gname = (char *)getitem(LLVM_LONGTERM_AREA, strlen(va_start_name) + 35); - sprintf(gname, "declare void %s(i8*)", va_start_name); + sprintf(gname, "declare void %s(ptr)", va_start_name); exfunc = (EXFUNC_LIST *)getitem(LLVM_LONGTERM_AREA, sizeof(EXFUNC_LIST)); memset(exfunc, 0, sizeof(EXFUNC_LIST)); exfunc->func_def = gname; @@ -4587,7 +4587,7 @@ gen_va_end(int ilix) if (!va_end_defined) { va_end_defined = true; gname = (char *)getitem(LLVM_LONGTERM_AREA, strlen(va_end_name) + 35); - sprintf(gname, "declare void %s(i8*)", va_end_name); + sprintf(gname, "declare void %s(ptr)", va_end_name); exfunc = (EXFUNC_LIST *)getitem(LLVM_LONGTERM_AREA, sizeof(EXFUNC_LIST)); memset(exfunc, 0, sizeof(EXFUNC_LIST)); exfunc->func_def = gname; @@ -6489,6 +6489,13 @@ make_bitcast(OPERAND *cast_op, LL_Type *rslt_type) TMPS *new_tmps; INSTR_LIST *Curr_Instr, *instr; + if (cast_op->ll_type->data_type == LL_PTR && + rslt_type->data_type == LL_PTR) { + operand = gen_copy_op(cast_op); + operand->ll_type = rslt_type; + return operand; + } + if (strict_match(cast_op->ll_type, rslt_type)) return gen_copy_op(cast_op); @@ -6950,11 +6957,7 @@ make_load(int ilix, OPERAND *load_op, LL_Type *rslt_type, MSZ msz, return cse_op; } } - if (load_op->ot_type == OT_VAR && ll_type_is_pointer_to_function(rslt_type)) { - load_type = LLTYPE(load_op->val.sptr); - } else { - load_type = load_op->ll_type; - } + load_type = load_op->ll_type; DBGTRACEIN2(" ilix %d, load op: %p", ilix, load_op) DBGDUMPLLTYPE("result type ", rslt_type) @@ -14138,66 +14141,15 @@ reset_expr_id(void) static void store_return_value_for_entry(OPERAND *p, int i_name) { - TMPS *tmp = make_tmps(); - - if (p->ot_type != OT_VAR || !DT_ISCMPLX(DTYPEG(p->val.sptr))) { - print_token("\t"); - print_tmp_name(tmp); - print_token(" = bitcast "); - write_type(make_generic_dummy_lltype()); - print_token(" %"); - print_token(get_entret_arg_name()); - print_token(" to "); - write_type(make_ptr_lltype(p->ll_type)); - print_nl(); - - print_token("\tstore "); - write_type(p->ll_type); - print_space(1); - write_operand(p, "", FLG_OMIT_OP_TYPE); - print_token(", "); - - write_type(make_ptr_lltype(p->ll_type)); - print_space(1); - print_tmp_name(tmp); - print_token(", align 4\n"); - } else { - TMPS *loadtmp; - /* %10 = bitcast i64* %__master_entry_rslt323 to <{float, float}>* */ - print_token("\t"); - print_tmp_name(tmp); - print_token(" = bitcast "); - write_type(make_generic_dummy_lltype()); - print_token(" %"); - print_token(get_entret_arg_name()); - print_token(" to "); - write_type(p->ll_type); - print_nl(); - - /* %11 = load <{float, float}>, <{float, float}>* %cp1_300, align 4 */ - loadtmp = make_tmps(); - print_token("\t"); - print_tmp_name(loadtmp); - print_token(" = load"); - write_type(p->ll_type->sub_types[0]); - print_token(", "); - write_type(p->ll_type); - print_space(1); - write_operand(p, "", FLG_OMIT_OP_TYPE); - print_token(", align 4\n"); - - /* store <{float, float}> %11, <{float, float}>* %10, align 4 */ - print_token("\tstore "); - write_type(p->ll_type->sub_types[0]); - print_space(1); - print_tmp_name(loadtmp); - print_token(", "); - - write_type(p->ll_type); - print_space(1); - print_tmp_name(tmp); - print_token(", align 4\n"); - } + print_token("\tstore "); + write_type(p->ll_type); + print_space(1); + write_operand(p, "", FLG_OMIT_OP_TYPE); + print_token(", "); + write_type(make_ptr_lltype(p->ll_type)); + print_token(" %"); + print_token(get_entret_arg_name()); + print_token(", align 4\n"); print_token("\t"); print_token(llvm_instr_names[i_name]); diff --git a/tools/flang2/flang2exe/ll_ftn.cpp b/tools/flang2/flang2exe/ll_ftn.cpp index 71a05126fbc2..1fffb6726de9 100644 --- a/tools/flang2/flang2exe/ll_ftn.cpp +++ b/tools/flang2/flang2exe/ll_ftn.cpp @@ -1079,7 +1079,7 @@ print_entry_subroutine(LL_Module *module) LL_Type *dummy_type; hashset_t formals; /* List of formal params for each entry trampoline */ sclen *pd_len = NULL, *pd_len_last = NULL; - bool has_char_args; + bool has_char_args, ret_scalar; SPTR arg; if (SYMLKG(sptr) <= NOSYM) @@ -1129,23 +1129,7 @@ print_entry_subroutine(LL_Module *module) } else { rettype = DT_NONE; } - if (fval && SCG(fval) != SC_DUMMY && SCG(fval) != SC_BASED) { - /* Bitcast fval which is local variable to i8*. - * We will pass this fval to master routine. - */ - tmp = make_tmps(); - tmp->id = 0; - print_token("\t"); - print_tmp_name(tmp); - print_token(" = bitcast "); - write_type(make_ptr_lltype(make_lltype_from_dtype(rettype))); - print_space(1); - print_token(SNAME(fval)); - print_token(" to "); - write_type(dummy_type); - print_space(1); - print_nl(); - } + ret_scalar = fval && SCG(fval) != SC_DUMMY && SCG(fval) != SC_BASED; /* call the master */ if (gbl.arets) { @@ -1169,12 +1153,11 @@ print_entry_subroutine(LL_Module *module) /* if function, the second argument is the return value. The third argument can also be a return value if the return value is a dummy argument (happens when types are different). */ - if (tmp) { - /* pass the tmp about */ + if (ret_scalar) { print_token(", "); write_type(dummy_type); print_space(1); - print_tmp_name(tmp); + print_token(SNAME(fval)); } else if (fval && SCG(fval) != SC_DUMMY && SCG(fval) != SC_BASED && fval != FVALG(gbl.currsub)) { TY_KIND ThisIsABug; // FIXME @@ -1227,7 +1210,7 @@ print_entry_subroutine(LL_Module *module) } if (i == 0) continue; /* skip choice */ - if (tmp && i == 1) + if (ret_scalar && i == 1) continue; /* skip return value */ print_token(", "); if (PASSBYVALG(sym)) @@ -1253,7 +1236,7 @@ print_entry_subroutine(LL_Module *module) int sym = *dpdscp++; if (i == 0) /* Skip choice */ continue; - if (tmp && i == 1) + if (ret_scalar && i == 1) continue; /* Skip non-character, return value */ if (DTYG(DTYPEG(sym)) == TY_CHAR || DTYG(DTYPEG(sym)) == TY_NCHAR) { clen = CLENG(sym); @@ -1286,14 +1269,14 @@ print_entry_subroutine(LL_Module *module) print_token(")\n\t"); - if (tmp) { + if (ret_scalar) { /* load return value and return it */ LL_Type *return_ll_type; if (!DT_ISCMPLX(rettype) || !CMPLXFUNC_C) { return_ll_type = make_lltype_from_dtype(rettype); - /* %1 = load i32, i32* %cp1_300, align 4 */ + /* %1 = load i32, ptr %cp1_300, align 4 */ tmp = make_tmps(); print_tmp_name(tmp); print_token(" = load "); @@ -1309,21 +1292,9 @@ print_entry_subroutine(LL_Module *module) print_nl(); } else { /* complex entry, default C return conventions */ - TMPS *addrtmp; return_ll_type = make_lltype_from_abi_arg(&abi->arg[0]); - /* %1 = bitcast <{float, float}>* %cp1_300 to double* */ - addrtmp = make_tmps(); - print_tmp_name(addrtmp); - print_token(" = bitcast "); - write_type(make_ptr_lltype(make_lltype_from_dtype(rettype))); - print_space(1); - print_token(SNAME(fval)); - print_token(" to "); - write_type(make_ptr_lltype(return_ll_type)); - print_nl(); - - /* %2 = load double, double* %1, align 4 */ + /* %1 = load double, ptr %cp1_300, align 4 */ tmp = make_tmps(); print_token("\t"); print_tmp_name(tmp); @@ -1333,7 +1304,7 @@ print_entry_subroutine(LL_Module *module) print_token(", "); write_type(make_ptr_lltype(return_ll_type)); print_space(1); - print_tmp_name(addrtmp); + print_token(SNAME(fval)); print_token(", align 4\n"); } if (abi->extend_abi_return) { diff --git a/tools/flang2/flang2exe/ll_write.cpp b/tools/flang2/flang2exe/ll_write.cpp index 1b77a56f87d4..d65f2155ea42 100644 --- a/tools/flang2/flang2exe/ll_write.cpp +++ b/tools/flang2/flang2exe/ll_write.cpp @@ -728,8 +728,8 @@ ll_write_local_objects(FILE *out, LL_Function *function) assert(object->sptr && strcmp(object->address.data, SNAME(object->sptr)), "Missing local storage", object->sptr, ERR_Fatal); LL_Type * llt = make_lltype_from_sptr((SPTR)object->sptr); - fprintf(out, "\t%s = bitcast %s* %s to %s", - SNAME(object->sptr), object->type->str, object->address.data, llt->str); + fprintf(out, "\t%s = bitcast ptr %s to %s", + SNAME(object->sptr), object->address.data, llt->str); fputc('\n', out); } #endif @@ -738,60 +738,40 @@ ll_write_local_objects(FILE *out, LL_Function *function) if (XBIT(217, 0x1)) { name = object->address.data; if (ll_type_bytes(object->type) == 4) { - if (object->type->data_type == LL_I32) { - fprintf(out, "\tstore i32 %s, i32* %s, align 4\n", - POWER_STACK_32_BIT_NAN, name); - } else { - fprintf(out, "\t%s.temp = bitcast %s* %s to i32*\n", name, - object->type->str, name); - fprintf(out, "\tstore i32 %s, i32* %s.temp, align 4\n", - POWER_STACK_32_BIT_NAN, name); - } + fprintf(out, "\tstore i32 %s, ptr %s, align 4\n", + POWER_STACK_32_BIT_NAN, name); } else if (ll_type_bytes(object->type) == 8) { - if (object->type->data_type == LL_I64) { - fprintf(out, "\tstore i64 %s, i64* %s, align 8\n", - POWER_STACK_64_BIT_NAN, name); - } else { - fprintf(out, "\t%s.temp = bitcast %s* %s to i64*\n", name, - object->type->str, name); - fprintf(out, "\tstore i64 %s, i64* %s.temp, align 8\n", - POWER_STACK_64_BIT_NAN, name); - } + fprintf(out, "\tstore i64 %s, ptr %s, align 8\n", + POWER_STACK_64_BIT_NAN, name); } else if (ll_type_bytes(object->type) > 4) { - fprintf(out, "\t%s.temp = bitcast %s* %s to i32*\n", name, - object->type->str, name); - fprintf(out, "\t%s.ptr = alloca i32*, align 4\n", name); + fprintf(out, "\t%s.ptr = alloca ptr, align 4\n", name); fprintf(out, "\t%s.count = alloca i32, align 4\n", name); - fprintf(out, "\tstore i32 %d, i32* %s.count, align 4\n", + fprintf(out, "\tstore i32 %d, ptr %s.count, align 4\n", (int)(ll_type_bytes(object->type) / 4), name); - fprintf(out, "\t%s.temp0 = bitcast i32* %s.temp to i8*\n", name, name); - fprintf(out, "\t%s.temp1 = bitcast i32** %s.ptr to i8**\n", name, name); - fprintf(out, "\tstore i8* %s.temp0, i8** %s.temp1, align 4\n", name, + fprintf(out, "\tstore ptr %s, ptr %s.ptr, align 4\n", name, name); fprintf(out, "\tbr label %%L.st.init.%04d.1\n", curr_nan_label_count); fprintf(out, "L.st.init.%04d.1:\n", curr_nan_label_count); - fprintf(out, "\t%s.temp2 = load i32, i32* %s.count, align 4\n", name, + fprintf(out, "\t%s.temp = load i32, ptr %s.count, align 4\n", name, name); - fprintf(out, "\t%s.temp3 = icmp sle i32 %s.temp2, 0\n", name, name); + fprintf(out, "\t%s.temp0 = icmp sle i32 %s.temp, 0\n", name, name); fprintf(out, - "\tbr i1 %s.temp3, label %%L.st.init.%04d.0," + "\tbr i1 %s.temp0, label %%L.st.init.%04d.0," " label %%L.st.init.%04d.2\n", name, curr_nan_label_count + 1, curr_nan_label_count); fprintf(out, "L.st.init.%04d.2:\n", curr_nan_label_count); - fprintf(out, "\t%s.temp4 = load i32*, i32** %s.ptr, align 4\n", name, + fprintf(out, "\t%s.temp1 = load ptr, ptr %s.ptr, align 4\n", name, name); - fprintf(out, "\tstore i32 %s, i32* %s.temp4, align 4\n", + fprintf(out, "\tstore i32 %s, ptr %s.temp1, align 4\n", POWER_STACK_32_BIT_NAN, name); - fprintf(out, "\t%s.temp5 = bitcast i32* %s.temp4 to i8*\n", name, name); - fprintf(out, "\t%s.temp6 = getelementptr i8, i8* %s.temp5, i32 4\n", + fprintf(out, "\t%s.temp2 = getelementptr i8, ptr %s.temp1, i32 4\n", name, name); - fprintf(out, "\t%s.temp7 = bitcast i32** %s.ptr to i8**\n", name, name); - fprintf(out, "\tstore i8* %s.temp6, i8** %s.temp7, align 4\n", name, + fprintf(out, "\tstore ptr %s.temp2, ptr %s.ptr, align 4\n", name, name); - fprintf(out, "\t%s.temp8 = load i32, i32* %s.count, align 4\n", name, + fprintf(out, "\t%s.temp3 = load i32, ptr %s.count, align 4\n", name, name); - fprintf(out, "\t%s.temp9 = sub i32 %s.temp8, 1\n", name, name); - fprintf(out, "\tstore i32 %s.temp9, i32* %s.count, align 4\n", name, + fprintf(out, "\t%s.temp4 = sub i32 %s.temp3, 1\n", name, name); + fprintf(out, "\tstore i32 %s.temp4, ptr %s.count, align 4\n", name, name); fprintf(out, "\tbr label %%L.st.init.%04d.1\n", curr_nan_label_count); curr_nan_label_count++; diff --git a/tools/flang2/flang2exe/llassem_common.cpp b/tools/flang2/flang2exe/llassem_common.cpp index 8e2b64d5812f..0d9ec9a5c78c 100644 --- a/tools/flang2/flang2exe/llassem_common.cpp +++ b/tools/flang2/flang2exe/llassem_common.cpp @@ -266,7 +266,7 @@ emit_init(DTYPE tdtype, ISZ_T tconval, ISZ_T *addr, ISZ_T *repeat_cnt, #ifdef OMP_OFFLOAD_LLVM // TODO ompaccel. Hackery for TGT structs. It must be fixed later. if (flg.omptarget) - fprintf(ASMFIL, " i8* "); + fprintf(ASMFIL, " ptr "); else #endif *cptr = put_next_member(*cptr); @@ -282,7 +282,7 @@ emit_init(DTYPE tdtype, ISZ_T tconval, ISZ_T *addr, ISZ_T *repeat_cnt, #ifdef OMP_OFFLOAD_LLVM // TODO ompaccel. Hackery for TGT structs. It must be fixed later. if (flg.omptarget) - fprintf(ASMFIL, " i8* "); + fprintf(ASMFIL, " ptr "); else #endif *cptr = put_next_member(*cptr);