Index: include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- include/llvm/CodeGen/SelectionDAGNodes.h +++ include/llvm/CodeGen/SelectionDAGNodes.h @@ -2015,6 +2015,9 @@ /// For integers this is the same as doing a TRUNCATE and storing the result. /// For floats, it is the same as doing an FP_ROUND and storing the result. bool isTruncatingStore() const { return StoreSDNodeBits.IsTruncating; } + void setTruncatingStore(bool Truncating) { + StoreSDNodeBits.IsTruncating = Truncating; + } const SDValue &getValue() const { return getOperand(1); } const SDValue &getBasePtr() const { return getOperand(2); } Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -12215,9 +12215,24 @@ cast(N)->getMemOperand()); } + // STORE Constant:i32<0> -> STORE Constant:i64<0> + // So it can increase the chance of CSE constant construction. + EVT VT = N->getOperand(1).getValueType(); + if (Subtarget.isPPC64() && !DCI.isBeforeLegalize() && + isa(N->getOperand(1)) && VT == MVT::i32) { + SDValue Const64 = DAG.getConstant(N->getConstantOperandVal(1), dl, + MVT::i64); + // DAG.getTruncStore() can't be used here because it doesn't accept + // the general (base + offset) addressing mode. + // So we use UpdateNodeOperands and setTruncatingStore instead. + DAG.UpdateNodeOperands(N, N->getOperand(0), Const64, N->getOperand(2), + N->getOperand(3)); + cast(N)->setTruncatingStore(true); + return SDValue(N, 0); + } + // For little endian, VSX stores require generating xxswapd/lxvd2x. // Not needed on ISA 3.0 based CPUs since we have a non-permuting store. - EVT VT = N->getOperand(1).getValueType(); if (VT.isSimple()) { MVT StoreVT = VT.getSimpleVT(); if (Subtarget.needsSwapsForVSXMemOps() && Index: test/CodeGen/PowerPC/store-constant.ll =================================================================== --- test/CodeGen/PowerPC/store-constant.ll +++ test/CodeGen/PowerPC/store-constant.ll @@ -0,0 +1,44 @@ +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr8 -verify-machineinstrs | FileCheck %s + +; Test the same constant can be used by different stores. + +%struct.S = type { i64, i8, i16, i32 } + +define void @foo(%struct.S* %p) { + %l4 = bitcast %struct.S* %p to i64* + store i64 0, i64* %l4, align 8 + %c = getelementptr %struct.S, %struct.S* %p, i64 0, i32 1 + store i8 0, i8* %c, align 8 + %s = getelementptr %struct.S, %struct.S* %p, i64 0, i32 2 + store i16 0, i16* %s, align 2 + %i = getelementptr %struct.S, %struct.S* %p, i64 0, i32 3 + store i32 0, i32* %i, align 4 + ret void + +; CHECK-LABEL: @foo +; CHECK: li 4, 0 +; CHECK: stb 4, 8(3) +; CHECK: std 4, 0(3) +; CHECK: sth 4, 10(3) +; CHECK: stw 4, 12(3) +} + +define void @bar(%struct.S* %p) { + %i = getelementptr %struct.S, %struct.S* %p, i64 0, i32 3 + store i32 2, i32* %i, align 4 + %s = getelementptr %struct.S, %struct.S* %p, i64 0, i32 2 + store i16 2, i16* %s, align 2 + %c = getelementptr %struct.S, %struct.S* %p, i64 0, i32 1 + store i8 2, i8* %c, align 8 + %l4 = bitcast %struct.S* %p to i64* + store i64 2, i64* %l4, align 8 + ret void + +; CHECK-LABEL: @bar +; CHECK: li 4, 2 +; CHECK: stw 4, 12(3) +; CHECK: sth 4, 10(3) +; CHECK: std 4, 0(3) +; CHECK: stb 4, 8(3) +} +