From a4b6404cf0ad8fae26188d780d583ef499f99b3b Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Mon, 28 Nov 2011 20:42:56 +0000 Subject: [PATCH] DAG combine should not increase alignment of loads / stores with alignment less than ABI alignment. These are loads / stores from / to "packed" data structures. Their alignments are intentionally under-specified. rdar://10301431 llvm-svn: 145273 --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 38 +++++++++++++------ .../CodeGen/ARM/2011-11-28-DAGCombineBug.ll | 38 +++++++++++++++++++ llvm/test/CodeGen/X86/widen_load-1.ll | 3 +- 3 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/2011-11-28-DAGCombineBug.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d8208a443387..2c4886a3c83c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -6206,13 +6206,20 @@ SDValue DAGCombiner::visitLOAD(SDNode *N) { // Try to infer better alignment information than the load already has. if (OptLevel != CodeGenOpt::None && LD->isUnindexed()) { - if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { - if (Align > LD->getAlignment()) - return DAG.getExtLoad(LD->getExtensionType(), N->getDebugLoc(), - LD->getValueType(0), - Chain, Ptr, LD->getPointerInfo(), - LD->getMemoryVT(), - LD->isVolatile(), LD->isNonTemporal(), Align); + unsigned ABIAlign = TLI.getTargetData()-> + getABITypeAlignment(LD->getMemoryVT().getTypeForEVT(*DAG.getContext())); + unsigned LDAlign = LD->getAlignment(); + // Do not touch loads with explicit alignments that are smaller than ABI + // alignment to avoid breaking loads from "packed" types. + if (!LDAlign || LDAlign >= ABIAlign) { + if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { + if (Align > LDAlign) + return DAG.getExtLoad(LD->getExtensionType(), N->getDebugLoc(), + LD->getValueType(0), + Chain, Ptr, LD->getPointerInfo(), + LD->getMemoryVT(), + LD->isVolatile(), LD->isNonTemporal(), Align); + } } } @@ -6669,11 +6676,18 @@ SDValue DAGCombiner::visitSTORE(SDNode *N) { // Try to infer better alignment information than the store already has. if (OptLevel != CodeGenOpt::None && ST->isUnindexed()) { - if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { - if (Align > ST->getAlignment()) - return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, - Ptr, ST->getPointerInfo(), ST->getMemoryVT(), - ST->isVolatile(), ST->isNonTemporal(), Align); + unsigned ABIAlign = TLI.getTargetData()-> + getABITypeAlignment(ST->getMemoryVT().getTypeForEVT(*DAG.getContext())); + unsigned STAlign = ST->getAlignment(); + // Do not touch stores with explicit alignments that are smaller than ABI + // alignment to avoid breaking stores from "packed" types. + if (!STAlign || STAlign >= ABIAlign) { + if (unsigned Align = DAG.InferPtrAlignment(Ptr)) { + if (Align > STAlign) + return DAG.getTruncStore(Chain, N->getDebugLoc(), Value, + Ptr, ST->getPointerInfo(), ST->getMemoryVT(), + ST->isVolatile(), ST->isNonTemporal(),Align); + } } } diff --git a/llvm/test/CodeGen/ARM/2011-11-28-DAGCombineBug.ll b/llvm/test/CodeGen/ARM/2011-11-28-DAGCombineBug.ll new file mode 100644 index 000000000000..5409f8c60887 --- /dev/null +++ b/llvm/test/CodeGen/ARM/2011-11-28-DAGCombineBug.ll @@ -0,0 +1,38 @@ +; RUN: llc < %s -mtriple=thumbv7-apple-ios5.0.0 | FileCheck %s +; rdar://10464621 + +; DAG combine increases loads from packed types. ARM load / store optimizer then +; combined them into a ldm which causes runtime exception. + +%struct.InformationBlock = type <{ i32, %struct.FlagBits, %struct.FlagBits }> +%struct.FlagBits = type <{ [4 x i32] }> + +@infoBlock = external global %struct.InformationBlock + +define hidden void @foo() { +; CHECK: foo: +; CHECK: ldr.w +; CHECK: ldr.w +; CHECK-NOT: ldm +entry: + %tmp13 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 1, i32 0, i32 0), align 1 + %tmp15 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 1, i32 0, i32 1), align 1 + %tmp17 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 1, i32 0, i32 2), align 1 + %tmp19 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 1, i32 0, i32 3), align 1 + %tmp = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 2, i32 0, i32 0), align 1 + %tmp3 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 2, i32 0, i32 1), align 1 + %tmp4 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 2, i32 0, i32 2), align 1 + %tmp5 = load i32* getelementptr inbounds (%struct.InformationBlock* @infoBlock, i32 0, i32 2, i32 0, i32 3), align 1 + %insert21 = insertvalue [4 x i32] undef, i32 %tmp13, 0 + %insert23 = insertvalue [4 x i32] %insert21, i32 %tmp15, 1 + %insert25 = insertvalue [4 x i32] %insert23, i32 %tmp17, 2 + %insert27 = insertvalue [4 x i32] %insert25, i32 %tmp19, 3 + %insert = insertvalue [4 x i32] undef, i32 %tmp, 0 + %insert7 = insertvalue [4 x i32] %insert, i32 %tmp3, 1 + %insert9 = insertvalue [4 x i32] %insert7, i32 %tmp4, 2 + %insert11 = insertvalue [4 x i32] %insert9, i32 %tmp5, 3 + tail call void @bar([4 x i32] %insert27, [4 x i32] %insert11) + ret void +} + +declare void @bar([4 x i32], [4 x i32]) diff --git a/llvm/test/CodeGen/X86/widen_load-1.ll b/llvm/test/CodeGen/X86/widen_load-1.ll index 639617f17774..a9fd19041840 100644 --- a/llvm/test/CodeGen/X86/widen_load-1.ll +++ b/llvm/test/CodeGen/X86/widen_load-1.ll @@ -1,5 +1,6 @@ ; RUN: llc %s -o - -march=x86-64 -mtriple=x86_64-unknown-linux-gnu | FileCheck %s ; PR4891 +; PR5626 ; This load should be before the call, not after. @@ -20,7 +21,7 @@ define void @reset(<2 x float>* noalias %garbage1) { store i32 0, i32* %changed, align 4 %r2 = getelementptr float* bitcast ([20 x i64]* @compl to float*), i64 32 ; [#uses=1] %r3 = bitcast float* %r2 to <2 x float>* ; <<2 x float>*> [#uses=1] - %r4 = load <2 x float>* %r3, align 4 ; <<2 x float>> [#uses=1] + %r4 = load <2 x float>* %r3, align 8 ; <<2 x float>> [#uses=1] call void @killcommon(i32* %changed) br label %"file complex.c, line 34, bb4"