[llvm] r214322 - Retain alignment requirements for load->selects modified by DAGCombine

Louis Gerbarg lgg at apple.com
Wed Jul 30 11:24:41 PDT 2014


Author: louis
Date: Wed Jul 30 13:24:41 2014
New Revision: 214322

URL: http://llvm.org/viewvc/llvm-project?rev=214322&view=rev
Log:
Retain alignment requirements for load->selects modified by DAGCombine

DAGCombine may choose to rewrite graphs where two loads feed a select into
graphs where a select of two addresses feed a load. While it sanity checks the
loads to make sure they are broadly equivalent it currently just uses the
alignment restriction of the left node. In cases where the right node has
stronger alignment requiresment this may lead to bad codegen, such as generating
an aligned load where an unaligned load is required. This patch makes the
combine generate a load with an alignment that is the same as whichever is more
restrictive of the two alignments.

Tests included.

rdar://17762530

Added:
    llvm/trunk/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp?rev=214322&r1=214321&r2=214322&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/DAGCombiner.cpp Wed Jul 30 13:24:41 2014
@@ -11181,13 +11181,17 @@ bool DAGCombiner::SimplifySelectOps(SDNo
     }
 
     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(SDNo
                             // 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.

Added: llvm/trunk/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll?rev=214322&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll (added)
+++ llvm/trunk/test/CodeGen/X86/x86-mixed-alignment-dagcombine.ll Wed Jul 30 13:24:41 2014
@@ -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
+}





More information about the llvm-commits mailing list