【问题标题】:Seemingly unnecessary bitcast -> phi -> bitcast being generated看似不必要的 bitcast -> phi -> 正在生成 bitcast
【发布时间】:2020-11-08 12:06:28
【问题描述】:

我遇到了一个问题,Clang 似乎生成了不必要的比特广播(从 f32 -> i32 -> f32。下面的部分是生成的 IR(去掉了不相关的部分。我尝试突出显示相关行,但这不起作用在代码块中。

问题在于定义 %5 的位转换,然后是重复的 phi 节点(%6 和 %7),以及最后一行的位转换存储。我看不出这个数据路径被比特广播到 i32 的原因,它没有在其他任何地方使用。

对应的c代码只包含float数据类型,一些以嵌套数组作为数据类型的structs,if elseif else构造了一些浮点常量(就是生成代码)。不知道为什么。

(ccode:https://pastebin.com/c0gYkwhF,llvm ir:https://pastebin.com/NSyhSkUa

tldr;

  • 为什么生成到 i32 的位广播
  • 我能否以某种方式阻止这种情况(不想处理 i32 数据类型)
; Function Attrs: nofree norecurse nounwind uwtable
define dso_local void @CurrentControl_step() local_unnamed_addr #0 {
entry:
; (...)
  %mul3 = fmul fast float %4, 0x3FEFFFEF80000000
  %add4 = fadd fast float %3, %mul3
  %cmp = fcmp fast ogt float %add4, 0x3FEF400000000000
  br i1 %cmp, label %if.then, label %if.else

; (...)

if.else7:                                         ; preds = %if.else
  store float %add4, float* getelementptr inbounds (%struct.DW_CurrentControl_T, %struct.DW_CurrentControl_T* @CurrentControl_DW, i64 0, i32 1, i64 0), align 4, !tbaa !2
  %5 = bitcast float %add4 to i32
  br label %if.end8

if.end8:                                          ; preds = %if.then6, %if.else7, %if.then
  %6 = phi i32 [ -1082523648, %if.then6 ], [ %5, %if.else7 ], [ 1064960000, %if.then ]
  %7 = phi float [ 0xBFEF400000000000, %if.then6 ], [ %add4, %if.else7 ], [ 0x3FEF400000000000, %if.then ]
; (...)
  %9 = fsub fast float %7, %mul9
; (...)
  store i32 %6, i32* bitcast (float* getelementptr inbounds (%struct.DW_CurrentControl_T, %struct.DW_CurrentControl_T* @CurrentControl_DW, i64 0, i32 2, i64 0) to i32*), align 4, !tbaa !2
; (...)

编辑: 我有一个新的最小示例生成看似不必要的比特广播:

typedef struct {
    float nestedArray[2];
} Foo;

Foo s;
float testVar;

void test(void) {
    testVar = s.nestedArray[0];
}

生成:

%struct.Foo = type { [2 x float] }

@s = dso_local local_unnamed_addr global %struct.Foo zeroinitializer, align 4
@var = dso_local local_unnamed_addr global float 0.000000e+00, align 4

; Function Attrs: nofree norecurse nounwind uwtable
define dso_local void @test() local_unnamed_addr #0 {
entry:
  %0 = load i32, i32* bitcast (%struct.Foo* @s to i32*), align 4, !tbaa !2
  store i32 %0, i32* bitcast (float* @var to i32*), align 4, !tbaa !2
  ret void
}

【问题讨论】:

  • 您的代码不完整;未显示使用的结构类型。但这可能无关紧要,因为有一种简单的方法可以找出 clang 的作用:在 CastInst::Create() 中设置断点,使其以 op 为条件,然后编译(简化版本)您的源代码。堆栈跟踪有你的答案。
  • @arnt 我在帖子底部添加了一个最小示例。我也尝试附加到铿锵声,但没有成功。但是,使用 -print-after-all 我设法弄清楚它实际上是添加了位广播的 InstCombine 通道。我尝试通过在文件上运行 opt -instcombine 进行复制,但这并没有插入额外的比特广播。编辑:-O0 到处添加 optnone 标志,没有那些 instcombine idd 添加额外的位广播

标签: clang llvm llvm-ir


【解决方案1】:

Bitcast 是由以下原因引起的:doc

// Try to canonicalize loads which are only ever stored to operate over
// integers instead of any other type. We only do this when the loaded type
// is sized and has a size exactly the same as its store size and the store
// size is a legal integer type.
// Do not perform canonicalization if minmax pattern is found (to avoid
// infinite loop).

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多