代码之家  ›  专栏  ›  技术社区  ›  keltar

gcc/clang对局部变量和结构字段使用restrict关键字

  •  3
  • keltar  · 技术社区  · 4 年前

    不知道如何说服gcc/clang我的指针不相交;在我看来 restrict 仅当在函数参数中指定时才使用,否则忽略。这是我的密码:

    #if defined(_MSC_VER) || defined(__cplusplus)
    #define restrict __restrict
    #endif
    
    struct s {
        int sz;
        int *a;
        int *b;
    };
    
    struct s_r {
        int sz;
        int *restrict a;
        int *restrict b;
    };
    
    void foo_dumb_struct(struct s *s, int c) {
        int sz = s->sz;
        for(int i = 0; i != sz; ++i) {
            s->a[i] = s->b[0] + c;
        }
    }
    
    void foo_restricted_arrays(int sz,
            int *restrict a, int *restrict b,
            int c) {
        for(int i = 0; i != sz; ++i) {
            a[i] = b[0] + c;
        }
    }
    
    void foo_restricted_struct(struct s_r *s, int c) {
        int sz = s->sz;
        for(int i = 0; i != sz; ++i) {
            s->a[i] = s->b[0] + c;
        }
    }
    
    void foo_restricted_subcall(struct s *s, int c) {
        foo_restricted_arrays(s->sz, s->a, s->b, c);
    }
    
    void foo_restricted_cast(struct s *s, int c) {
        int sz = s->sz;
        int *restrict a = s->a;
        int *restrict b = s->b;
        for(int i = 0; i != sz; ++i) {
            a[i] = b[0] + c;
        }
    }
    

    Icc可以使用此代码,但是gcc/clang会生成 b[0] 每次迭代 foo_restricted_struct foo_restricted_cast ,对于我可以用godbolt测试的所有架构。在函数参数中使用的任何时间(包括嵌套函数或C++ LAMBDAS)都很好,并且额外的负载被移除。 https://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html 这表明它实际上按我所希望的那样工作,但我不确定他们的gcc是否是专门为cell定制的。

    0 回复  |  直到 4 年前
        1
  •  2
  •   John Bollinger    4 年前

    在我看来 restrict

    这听起来像你想的 资格证书带有某种 义务

    译者可以随意忽略使用restrict的任何或所有别名含义。

    限制 在某些情况下,执行额外优化的限定条件在其他类似情况下不会起到相同的作用,但这并不意味着代码或编译器在任何方面都是错误的(但请记住埃里克关于限制合格结构件的观察。然而,所举的例子也不一定都像你想象的那样相似。

    我对restrict的用法是错误的,还是gcc/clang只对函数参数实现restrict而不实现其他功能?

    限制 -限定的块作用域变量,它们实际上不能用于很多用途。限制限定是一种将依赖性分析的责任从编译器转移到程序员的方法,但是程序员没有比编译器在诸如 foo_restricted_cast() a b

    限制 -合格的结构成员,我不同意另一个答案的断言,没有为他们定义语义。的确,结构构件的标识符不是“普通标识符”,而是本标准对结构构件定义的措辞 限制 语义似乎是专门设计的,目的是通过包含结构成员的结构对象的普通标识符的声明来覆盖结构成员。这种语言当然可以这样解读,如果不是这样的话,那就比平常更令人担忧了。

    因此,我认为 foo_restricted_struct() 有明确的语义,而且 icc 在利用 限制 gcc Clang 也不要利用正在进行的优化选项,但是他们没有义务这样做。

    foo_restricted_subcall() 表现出一个类似于 foo\u restricted\u cast() . 我认为有一个外部的机会,就是因为这个原因,GCC和/或Clang避免了更积极的优化 ,其中 具有语义上有问题的参数的调用。不过,这些编译器可能只是没有进行足够深入的分析,以了解本例中的优化机会。

        2
  •  2
  •   Eric Postpischil    4 年前

    restrict 结构构件的C标准中没有定义。

    形式化定义 限制 D 是普通标识符的声明

    6.2.3.1定义了排除结构或联合体成员的普通标识符:

    因此,对于各种类型的标识符有单独的名称空间,如下所示:

    标签名称

    这个 标签 结构、并集和枚举(通过遵循以下任一 关键词 结构 , 联盟 ,或 枚举 );

    这个 成员 结构或结合;每个结构或联合对其成员都有一个单独的名称空间(通过用于通过 运营商);

    所有其他标识符,称为 普通标识符 (在普通声明符中声明或作为枚举常量声明)。