The code which lowers BUILD_VECTOR of consecutive loads into a single vector load doesn't update chains properly. As a result the vector load can be reordered with the store to the same location.
Consider the test case.
define <4 x i32> @merge_4i32_i32_23u5_inc3(i32* %ptr) nounwind uwtable noinline ssp {
%ptr0 = getelementptr inbounds i32, i32* %ptr, i64 2
%ptr1 = getelementptr inbounds i32, i32* %ptr, i64 3
%ptr3 = getelementptr inbounds i32, i32* %ptr, i64 5
%val0 = load i32, i32* %ptr0
%val1 = load i32, i32* %ptr1
%inc = add i32 %val1, 1
store i32 %inc, i32* %ptr1
%val3 = load i32, i32* %ptr3
%res0 = insertelement <4 x i32> undef, i32 %val0, i32 0
%res1 = insertelement <4 x i32> %res0, i32 %val1, i32 1
%res3 = insertelement <4 x i32> %res1, i32 %val3, i32 3
ret <4 x i32> %res3
}llc -mtriple=x86_64-unknown-unknown -mattr=+sse2 -debug-only=isel
Type-legalized selection DAG: BB#0 'merge_4i32_i32_23u5_inc3:'
SelectionDAG has 22 nodes:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t6: i64 = add t2, Constant:i64<12>
t11: i32,ch = load<LD4[%ptr1]> t0, t6, undef:i64
t13: i32 = add t11, Constant:i32<1>
t14: ch = store<ST4[%ptr1]> t11:1, t13, t6, undef:i64
t4: i64 = add t2, Constant:i64<8>
t35: i32,ch = load<LD4[%ptr0]> t0, t4, undef:i64
t8: i64 = add t2, Constant:i64<20>
t33: i32,ch = load<LD4[%ptr3]> t0, t8, undef:i64
t32: v4i32 = BUILD_VECTOR t35, t11, undef:i32, t33
t27: ch,glue = CopyToReg t14, Register:v4i32 %XMM0, t32
t28: ch = X86ISD::RET_FLAG t27, TargetConstant:i32<0>, Register:v4i32 %XMM0, t27:1Legalized selection DAG: BB#0 'merge_4i32_i32_23u5_inc3:'
SelectionDAG has 18 nodes:
t0: ch = EntryToken
t2: i64,ch = CopyFromReg t0, Register:i64 %vreg0
t6: i64 = add t2, Constant:i64<12>
t11: i32,ch = load<LD4[%ptr1]> t0, t6, undef:i64
t13: i32 = add t11, Constant:i32<1>
t14: ch = store<ST4[%ptr1]> t11:1, t13, t6, undef:i64
t4: i64 = add t2, Constant:i64<8>
t38: v2i64,ch = load<LD16[%ptr0](align=4)> t0, t4, undef:i64
t39: v4i32 = bitcast t38
t27: ch,glue = CopyToReg t14, Register:v4i32 %XMM0, t39
t28: ch = X86ISD::RET_FLAG t27, TargetConstant:i32<0>, Register:v4i32 %XMM0, t27:1In the last DAG there are two chains:
t0 - t11 (scalar load) - t14 (scalar store)
t0 - t38 (vector load)
There is no ordering constraint between t38 (vector load) and t14 (scalar store), so they can be reordered. That's what happens in the final assembly:
# BB#0: incl 12(%rdi) movups 8(%rdi), %xmm0 retq
Here the scalar store happens before the vector load. The vector load reloads the incremented value for 12(%rdi) location, while in the original program it uses the pre-increment value.
The current code in EltsFromConsecutiveLoads tries to update the chains but fails becuase it only updates the chain following the first load. Had the incremented location been the first load we wouldn't miscompile. The fix is to update the chains following all the loads comprising the vector.