Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -12678,7 +12678,11 @@ SDValue Val = St->getValue(); StoreInt <<= ElementSizeBits; if (ConstantSDNode *C = dyn_cast(Val)) { - StoreInt |= C->getAPIntValue().zextOrTrunc(SizeInBits); + // Since the store may be truncating, the stored immediate must be + // truncated to the width of the element. + APInt CElt(ElementSizeBits, + C->getAPIntValue().zextOrTrunc(ElementSizeBits).getZExtValue()); + StoreInt |= CElt.zextOrTrunc(SizeInBits); } else if (ConstantFPSDNode *C = dyn_cast(Val)) { StoreInt |= C->getValueAPF().bitcastToAPInt().zextOrTrunc(SizeInBits); } else { Index: test/CodeGen/SystemZ/DAGCombiner_stores.ll =================================================================== --- /dev/null +++ test/CodeGen/SystemZ/DAGCombiner_stores.ll @@ -0,0 +1,40 @@ +; RUN: llc -mtriple=s390x-linux-gnu -mcpu=zEC12 < %s | FileCheck %s +; +; This (reduced csmith) test case stores a lot of 16 bit constant -7 values +; to adjacent locations, which the DAGCombiner will merge to wider stores. It +; was discovered that the result of combining two or four such stores +; resulted incorrectly in stores of 32-bit / 64-bit constants of value +; -7. The correct constant then is not -7, but consists of two or four i16 -7 +; elements. + +; CHECK-NOT: mvhi {{.*}} -7 + +@y = external unnamed_addr global [10 x [7 x i16]] + +define void @bad_merge() { + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 0, i64 2), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 0, i64 3), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 0, i64 4), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 2, i64 1), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 2, i64 3), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 3, i64 0), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 3, i64 1), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 3, i64 6), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 4, i64 3), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 4, i64 4), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 4, i64 5), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 5, i64 0), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 5, i64 2), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 5, i64 4), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 5, i64 6), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 6, i64 1), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 6, i64 4), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 7, i64 1), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 7, i64 5), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 8, i64 0), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 8, i64 4), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 8, i64 6), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 9, i64 5), align 2 + store i16 -7, i16* getelementptr inbounds ([10 x [7 x i16]], [10 x [7 x i16]]* @y, i64 0, i64 9, i64 6), align 2 + ret void +}