GCC Target Hook

Table of Contents

1. GCC Target Hook

https://gcc.gnu.org/onlinedocs/gccint/Target-Macros.html#Target-Macros

GCC Backend 的 example 里看到的

  • riscv_print_operand
  • riscv_print_operand_address
  • riscv_conditional_register_usage

都是 target hook.

target hook 定义在 target.def 中, 以 conditional_register_usage 为例:

  • riscv 通过 TARGET_CONDITIONAL_REGISTER_USAGE 定义一个 hook 的实现

    #define TARGET_CONDITIONAL_REGISTER_USAGE riscv_conditional_register_usage
    
  • 代码中通过 targetm.conditional_register_usage () 调用到 target hook

gcc 通过 target hook 和 macro 的方式允许 backend 针对某些功能提供自己的实现和相关的配置

1.1. runtime target 相关

1.1.1. TARGET_CPU_CPP_BUILTINS

这个 hook 会影响 gcc preprocessor, 通过 `builtin_define` 预定义了一些 runtime macro

void riscv_cpu_cpp_builtins(cpp_reader *pfile) {
    builtin_define("__riscv");

    if (TARGET_RVC) builtin_define("__riscv_compressed");

    if (TARGET_RVE) builtin_define("__riscv_32e");

    if (TARGET_ATOMIC) builtin_define("__riscv_atomic");

    if (TARGET_MUL) builtin_define("__riscv_mul");
    if (TARGET_DIV) builtin_define("__riscv_div");
    if (TARGET_DIV && TARGET_MUL) builtin_define("__riscv_muldiv");

    builtin_define_with_int_value("__riscv_xlen", UNITS_PER_WORD * 8);
    if (TARGET_HARD_FLOAT)
        builtin_define_with_int_value("__riscv_flen", UNITS_PER_FP_REG * 8);

    if (TARGET_HARD_FLOAT && TARGET_FDIV) {
        builtin_define("__riscv_fdiv");
        builtin_define("__riscv_fsqrt");
    }

    switch (riscv_abi) {
        case ABI_ILP32E:
            builtin_define("__riscv_abi_rve");
            gcc_fallthrough();

        case ABI_ILP32:
        case ABI_LP64:
            builtin_define("__riscv_float_abi_soft");
            break;

        case ABI_ILP32F:
        case ABI_LP64F:
            builtin_define("__riscv_float_abi_single");
            break;

        case ABI_ILP32D:
        case ABI_LP64D:
            builtin_define("__riscv_float_abi_double");
            break;
    }
    /* ... */
}

gcc 通过 march 定义了 TARGET_MUL 等 macro, 但它们是给 gcc 使用的. 应用代码如果要得到 TARGET_MUL 类似的功能, 需要使用 TARGET_CPU_CPP_BUILTINS 通过 builtin_define 定义的 __riscv_mul

通过 `echo| /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc -E -dM -` 可以看到所有的 predefined macro

$> echo| /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc  -E -dM -|grep -i riscv
#define __riscv 1
#define __riscv_atomic 1
#define __riscv_cmodel_medlow 1
#define __riscv_fdiv 1
#define __riscv_float_abi_double 1
#define __riscv_mul 1
#define __riscv_muldiv 1
#define __riscv_xlen 64
#define __riscv_fsqrt 1
#define __riscv_m 2000000
#define __riscv_a 2000000
#define __riscv_c 2000000
#define __riscv_d 2000000
#define __riscv_f 2000000
#define __riscv_i 2000000
#define __riscv_zicsr 2000000
#define __riscv_compressed 1
#define __riscv_flen 64
#define __riscv_arch_test 1
#define __riscv_div 1
#define __riscv_zifencei 2000000
Backlinks

GCC Builtin (GCC Builtin > builtin_define): TARGET_CPU_CPP_BUILTINS 通过 builtin_define 来定义 runtime builtin macro (例如 __riscv_mul)

1.1.2. TARGET_OS_CPP_BUILTINS

用来定义 `linux`, `__linux__` 等 os 相关的 runtime macro

1.1.3. TARGET_OPTION_OVERRIDE

1.1.4. TARGET_DEFAULT_TARGET_FLAGS

指定 target_flags 的默认值

1.1.5. TARGET_OPTION_OPTIMIZATION_TABLE

针对某个 opt level 打开某个 opt

1.1.6. TARGET_OPTION_INIT_STRUCT

修改 gcc option

1.1.7. TARGET_INIT_BUILTINS

Backlinks

GCC Builtin (GCC Builtin > builtins): target 自定义的 builtin 由 TARGET_INIT_BUILTINSTARGET_EXPAND_BUILTIN 定义和 实现.

1.1.8. TARGET_EXPAND_BUILTIN

Backlinks

GCC Builtin (GCC Builtin > builtins): target 自定义的 builtin 由 TARGET_INIT_BUILTINSTARGET_EXPAND_BUILTIN 定义和 实现.

1.2. storage layout 相关

1.2.1. endian

  • BITS_BIG_ENDIAN
  • BYTES_BIG_ENDIAN
  • WORDS_BIG_ENDIAN
  • REG_WORDS_BIG_ENDIAN
  • FLOAT_WORDS_BIG_ENDIAN

1.2.2. size

  • BITS_PER_WORD
  • POINTER_SIZE

1.2.3. align

  • PARM_BOUNDARY
  • STACK_BOUNDARY
  • FUNCTION_BOUNDARY
  • BIGGEST_ALIGNMENT
  • MALLOC_ABI_ALIGNMENT
  • ATTRIBUTE_ALIGNED_VALUE
  • BIGGEST_FIELD_ALIGNMENT
  • DATA_ALIGNMENT
  • LOCAL_ALIGNMENT
  • STRICT_ALIGNMENT

1.3. register 相关

pass_ira 会使用这些 macro

1.3.1. FIRST_PSEUDO_REGISTER

1.3.2. FIXED_REGISTERS

1.3.3. CALL_USED_REGISTERS

1.3.4. REG_ALLOC_ORDER

1.4. stack 相关

1.4.1. STACK_GROWS_DOWNWARD

1.4.2. FRAME_ADDR_RTX

1.4.3. RETURN_ADDR_RTX

这个宏会生成一个返回 `return address` 的 rtx, 主要用来支持 __builtin_return_address, 在 riscv 上就是返回 x1 (ra) 的值

1.4.4. STACK_POINTER_REGNUM

1.4.5. FRAME_POINTER_REGNUM

1.4.6. TARGET_STACK_PROTECT_GUARD

GCC Stack Protector 有关

1.4.7. TARGET_STACK_PROTECT_FAIL

1.5. cost 相关

1.5.2. TARGET_ADDRESS_COST

1.5.4. MEMORY_MOVE_COST

1.5.5. REGISTER_MOVE_COST

1.5.6. BRANCH_COST

1.5.7. SLOW_BYTE_ACCESS

1.5.8. MOVE_RATIO

是否使用 memcpy?

1.5.9. CLEAR_RATIO

是否使用 bzero?

1.5.10. SET_RATIO

是否使用 memset?

1.6. schedule 相关

1.6.2. TARGET_SCHED_ADJUST_COST

1.6.3. TARGET_SCHED_ADJUST_PRIORITY

1.6.4. TARGET_SCHED_REORDER

1.6.5.

1.7. assembler format

1.7.1. ASM_OUTPUT_LABEL

1.8. misc

1.8.1. TARGET_PRINT_OPERAND

1.8.2. TARGET_PRINT_OPERAND_ADDRESS

1.8.3. TARGET_CONDITIONAL_REGISTER_USAGE

1.8.4. TARGET_STRUCT_VALUE_RTX

用来设置 GCC Named Return Value 如何把 nrv 传递给 callee

例如:

#define TARGET_STRUCT_VALUE_RTX my_struct_value_rtx

static rtx my_struct_value_rtx(
    tree fntype ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED) {
    return gen_rtx_REG(Pmode, 13);
}

表示用 reg 13 (riscv 的 a3) 传递 nrv. 若该宏没有定义, 则会把 nrv 看做 callee 的第一个参数来处理

struct X {
    int a;
    int b;
    int c;
    int d;
    int e;
    int f;
};

struct X foo(int a) {
    struct X x = {0};
    x.a = a;
    return x;
}
$> /opt/riscv/bin/riscv64-unknown-linux-gnu-gcc  test.c -O1 -c
$> /opt/riscv/bin/riscv64-unknown-linux-gnu-objdump -d ./test.o

0000000000000000 <foo>:
   0:   c288                    sw      a0,0(a3)
   2:   0006a223                sw      zero,4(a3)
   6:   0006a423                sw      zero,8(a3)
   a:   0006a623                sw      zero,12(a3)
   e:   0006a823                sw      zero,16(a3)
  12:   0006aa23                sw      zero,20(a3)
  16:   8536                    mv      a0,a3
  18:   8082                    ret

1.8.5. TARGET_HAVE_PREFETCH

1.8.6. TARGET_OPTAB_SUPPORTED_P

Backlinks

GCC Backend (GCC Backend > misc > target hook): target hook

Author: [email protected]
Date: 2022-04-26 Tue 19:45
Last updated: 2022-11-11 Fri 11:01

知识共享许可协议