diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 5fb0ea9146e..c7c7f48dc63 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -11181,13 +11181,17 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, } SDValue Load; + // It is safe to replace the two loads if they have different alignments, + // but the new load must be the minimum (most restrictive) alignment of the + // inputs. + unsigned Alignment = std::min(LLD->getAlignment(),RLD->getAlignment()); if (LLD->getExtensionType() == ISD::NON_EXTLOAD) { Load = DAG.getLoad(TheSelect->getValueType(0), SDLoc(TheSelect), // FIXME: Discards pointer and AA info. LLD->getChain(), Addr, MachinePointerInfo(), LLD->isVolatile(), LLD->isNonTemporal(), - LLD->isInvariant(), LLD->getAlignment()); + LLD->isInvariant(), Alignment); } else { Load = DAG.getExtLoad(LLD->getExtensionType() == ISD::EXTLOAD ? RLD->getExtensionType() : LLD->getExtensionType(), @@ -11196,7 +11200,7 @@ bool DAGCombiner::SimplifySelectOps(SDNode *TheSelect, SDValue LHS, // FIXME: Discards pointer and AA info. LLD->getChain(), Addr, MachinePointerInfo(), LLD->getMemoryVT(), LLD->isVolatile(), - LLD->isNonTemporal(), LLD->getAlignment()); + LLD->isNonTemporal(), Alignment); } // Users of the select now use the result of the load. diff --git a/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll b/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll new file mode 100644 index 00000000000..555273f67da --- /dev/null +++ b/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll @@ -0,0 +1,35 @@ +; RUN: llc -mcpu=core2 -mattr=+64bit,+sse2 < %s | FileCheck %s + +; DAGCombine may choose to rewrite 2 loads feeding a select as a select of +; addresses feeding a load. This test ensures that when it does that it creates +; a load with alignment equivalent to the most restrictive source load. + +declare void @sink(<2 x double>) + +define void @test1(i1 %cmp) align 2 { + %1 = alloca <2 x double>, align 16 + %2 = alloca <2 x double>, align 8 + + %val = load <2 x double>* %1, align 16 + %val2 = load <2 x double>* %2, align 8 + %val3 = select i1 %cmp, <2 x double> %val, <2 x double> %val2 + call void @sink(<2 x double> %val3) + ret void + ; CHECK: test1 + ; CHECK: movups + ; CHECK: ret +} + +define void @test2(i1 %cmp) align 2 { + %1 = alloca <2 x double>, align 16 + %2 = alloca <2 x double>, align 8 + + %val = load <2 x double>* %1, align 16 + %val2 = load <2 x double>* %2, align 16 + %val3 = select i1 %cmp, <2 x double> %val, <2 x double> %val2 + call void @sink(<2 x double> %val3) + ret void + ; CHECK: test2 + ; CHECK: movaps + ; CHECK: ret +}