首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未定义的LLVM IR取决于数组大小

未定义的LLVM IR取决于数组大小
EN

Stack Overflow用户
提问于 2018-02-06 23:38:50
回答 1查看 187关注 0票数 0

我看到一个未定义的行为取决于本地数组的大小。对于下面的代码:

代码语言:javascript
复制
    int wbExecute_simple(char nInput, char add_pattern)
    {
        char test_array[4] = { 0xa, 0xb, 0xc, 0xd };
        int i = 0;
        for (; i < 4; ++i)
        {
            test_array[i] ^= nInput;
        }
        return (test_array[nInput] + add_pattern);
    }

第一行的LLVM IR表示为:

代码语言:javascript
复制
    lbl_0_wb3954:
    %local_0_wb3954 = alloca [4 x i8], align 1
    %local_1_wb3954 = bitcast [4 x i8]* %local_0_wb3954 to i32*, !dbg !7
    %local_2_wb3954 = bitcast [4 x i8]* @global_0_wb3954 to i32*
    %local_3_wb3954 = load i32* %local_2_wb3954, align 1, !dbg !7
    store i32 %local_3_wb3954, i32* %local_1_wb3954, align 1, !dbg !7
    br label %lbl_1_wb3954, !dbg !8

数组大小为2也会产生类似的结果。但是,将数组的大小从4改为3,如下所示:

代码语言:javascript
复制
    int wbExecute_simple(char nInput, char add_pattern)
    {
        char test_array[3] = { 0xa, 0xb, 0xc };
        int i = 0;
        for (; i < 3; ++i)
        {
        test_array[i] ^= nInput;
        }
        return (test_array[nInput] + add_pattern);
    }

收益率

代码语言:javascript
复制
    define i32 @wbExecute_simple(i8 signext %nInput, i8 signext %add_pattern) #0 {
        lbl_0_wb3954:
        %local_0_wb3954 = alloca [3 x i8], align 1
        %local_1_wb3954 = getelementptr inbounds [3 x i8]* %local_0_wb3954, i32 0, i32 0, !dbg !7
        %local_2_wb3954 = getelementptr [3 x i8]* @global_0_wb3954, i32 0, i32 0
        call void @llvm.memcpy.p0i8.p0i8.i32(i8* %local_1_wb3954, i8* %local_2_wb3954, i32 3, i32 1, i1 false), !dbg !7
        br label %lbl_1_wb3954, !dbg !8

是否有任何优化标志来使两个大小的数组的LLVM IR相同?

EN

回答 1

Stack Overflow用户

发布于 2018-02-07 01:17:02

我不确定你所说的未定义行为是什么意思。这看起来像是一个合法的编译器优化。

当数组的长度为4时,编译器通过复制单个整数来代替复制数组,因为这也具有4的大小,并且可以在一次操作中完成。我假设对于第二个大小,它将复制一个16位整数。

您的系统可能不支持任何24位整数,因此编译器决定不对大小为3的整数进行优化,而是将memcpy保留在内部。请注意,如果没有处理器和内存系统支持的"int24“类型,这种优化对于大小为3的数组是没有意义的。编译器后端可能会有进一步的优化,以改进剩余的memcpy固有特性,这取决于它在目标计算机上是否有意义。

我将对生成的IR进行注释,以阐明代码的作用:

代码语言:javascript
复制
   lbl_0_wb3954:
    // allocate the local array
    %local_0_wb3954 = alloca [4 x i8], align 1
    // cast the address of the local array to an integer pointer
    %local_1_wb3954 = bitcast [4 x i8]* %local_0_wb3954 to i32*, !dbg !7
    // cast the address of the constant array {  0xa, 0xb, 0xc, 0xd } to an integer pointer
    %local_2_wb3954 = bitcast [4 x i8]* @global_0_wb3954 to i32*
    // load the constant array as a 32 bit integer
    %local_3_wb3954 = load i32* %local_2_wb3954, align 1, !dbg !7
    // store the value to the local array
    store i32 %local_3_wb3954, i32* %local_1_wb3954, align 1, !dbg !7
    br label %lbl_1_wb3954, !dbg !8

我不认为这种类型的优化可以轻易地强制长度为3。

例如,传递-O2将导致长度为3的循环完全展开,并删除静态初始化,有利于将常量0xa0xb0xc内联到code中,大小为4的代码看起来类似。

代码语言:javascript
复制
  %3 = alloca [3 x i8], align 1
  // compute address of first array element
  %4 = getelementptr inbounds [3 x i8], [3 x i8]* %3, i64 0, i64 0, !dbg !22
  // compute 0xa ^ nInput;
  %5 = xor i8 %0, 10, !dbg !25
  // store the result
  store i8 %5, i8* %4, align 1, !dbg !25, !tbaa !29

  // do the same for the second and third elements
  %6 = getelementptr inbounds [3 x i8], [3 x i8]* %3, i64 0, i64 1, !dbg !32
  %7 = xor i8 %0, 11, !dbg !25
  store i8 %7, i8* %6, align 1, !dbg !25, !tbaa !29
  %8 = getelementptr inbounds [3 x i8], [3 x i8]* %3, i64 0, i64 2, !dbg !32
  %9 = xor i8 %0, 12, !dbg !25
  store i8 %9, i8* %8, align 1, !dbg !25, !tbaa !29
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48646681

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档