Reputation: 2469
I am having a problem where Clang is seemingly generating unnecessary bitcasts (from f32 -> i32 -> f32. The following piece is the generated IR (with stripped out irrelevant pieces. I tried highlighting the relevant lines but that does not work in a code block.
The problem is the bitcast defining %5, followed by the duplicated phi nodes (%6 and %7), and a bitcast store which is the last line. I don't see a reason why this datapath is bitcasted into i32, it is not being used anywhere else.
The corresponding c code contains only float data types, some structs with nested arrays as data types, if elseif else constructs with some floating point constants (it is generated code). No clue as on why.
(ccode: https://pastebin.com/c0gYkwhF, llvm ir: https://pastebin.com/NSyhSkUa)
tldr;
; 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
; (...)
EDIT: I have a new minimal example generating a seemingly unnecessary bitcast:
typedef struct {
float nestedArray[2];
} Foo;
Foo s;
float testVar;
void test(void) {
testVar = s.nestedArray[0];
}
which generates:
%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
}
Upvotes: 1
Views: 103
Reputation: 2469
Bitcast was caused by: 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).
Upvotes: 0