看似不必要的 bitcast -> phi -> 正在生成 bitcast
Seemingly unnecessary bitcast -> phi -> bitcast being generated
我遇到一个问题,Clang 似乎生成了不必要的位广播(从 f32 -> i32 -> f32。下面的部分是生成的 IR(删除了不相关的部分。我尝试突出显示相关行,但确实如此不适用于代码块。
问题在于定义 %5 的位播,后面是重复的 phi 节点(%6 和 %7),最后一行是位播存储。我看不出为什么将此数据路径位播到 i32 中的原因,它没有在其他任何地方使用。
相应的c代码只包含float数据类型,一些结构嵌套数组作为数据类型,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
}
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).
我遇到一个问题,Clang 似乎生成了不必要的位广播(从 f32 -> i32 -> f32。下面的部分是生成的 IR(删除了不相关的部分。我尝试突出显示相关行,但确实如此不适用于代码块。
问题在于定义 %5 的位播,后面是重复的 phi 节点(%6 和 %7),最后一行是位播存储。我看不出为什么将此数据路径位播到 i32 中的原因,它没有在其他任何地方使用。
相应的c代码只包含float数据类型,一些结构嵌套数组作为数据类型,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
}
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).