This is part of the series started by D68484.
Ensures that alloca's can be split and optimized away, while keeping
the noalias information correct.
Note: this is a stable point and tests should run fine with the patches applied up to this point.
jeroen.dobbelaere on Oct 4 2019, 3:13 PM.Authored by
Jeroen, we discovered an assertion in introduceNoAliasWhenCopyGuardIndicesAreCompatible() for the case described below; we would appreciate your input.
This function expects a GEP between a load and a copy.guard, however, it's not always so; consider the following case where there's a bitcast instruction instead:
%3 = call %struct.FOO* @llvm.noalias.copy.guard.p0s_struct.FOOs.p0i8(%struct.FOO* %ssrc, i8* %0, metadata !12, metadata !6) %src_bitcast = bitcast %struct.FOO* %3 to i32* %src_data = load i32, i32* %src_bitcast, noalias_sidechannel i32* undef, align 4, !noalias !6
On platforms with 32-bit pointers, pointers might be treated as 32-bit integers, hence the bitcast. I attach an llvm-lit test case, hope it helps.
I don't think that we can emit an llvm.noalias intrinsic here since the pointer is treated as a integer, so maybe we should just bail.. What do you think?
Is the bitcast introduced by 'clang' (frontend), or was it introduced by one of the optimization passes ? In the latter case, which pass is this? We should probably handle it and
If it is based on 'a pointer to int' conversion in the c-language, then it should be ok to just ignore it.
I looked into it, it is instruction combining that introduces the bitcasts. IR before:
%2 = call %"struct.std::_Array"* @"llvm.noalias.copy.guard.p0s_struct.std::_Arrays.p0i8"(%"struct.std::_Array"* %_M_array4, i8* null, metadata !13, metadata !2) %3 = bitcast %"struct.std::_Array"* %_M_array to i8* %4 = bitcast %"struct.std::_Array"* %2 to i8* call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %3, i8* align 4 %4, i32 4, i1 false)
%2 = call %"struct.std::_Array"* @"llvm.noalias.copy.guard.p0s_struct.std::_Arrays.p0i8"(%"struct.std::_Array"* nonnull %_M_array4, i8* null, metadata !44, metadata !47) %3 = bitcast %"struct.std::_Array"* %2 to i32* %4 = bitcast %"struct.std::_Array"* %_M_array to i32* %5 = load i32, i32* %3, align 4 store i32 %5, i32* %4, align 4
I'm trying to understand your suggestion of treating this kind of bitcasts as a zero-offset GEP, how would we insert an llvm.noalias intrinsic? The first operand of llvm.noalias obviously should be a pointer but the load above doesn't return a pointer, it returns an i32.