summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-09-30 23:19:55 +0000
committerBill Wendling <isanbard@gmail.com>2011-09-30 23:19:55 +0000
commite09b2a0d4964e6a34ea6393e94a9f5a76ba56f1a (patch)
tree37fd1d85ea872d3db5728a31c6ade397f1d1e6e9
parent8de34006cf4cd67ef11cac59dd037bb722b18166 (diff)
downloadllvm-e09b2a0d4964e6a34ea6393e94a9f5a76ba56f1a.tar.gz
llvm-e09b2a0d4964e6a34ea6393e94a9f5a76ba56f1a.tar.bz2
llvm-e09b2a0d4964e6a34ea6393e94a9f5a76ba56f1a.tar.xz
When inferring the pointer alignment, if the global doesn't have an initializer
and the alignment is 0 (i.e., it's defined globally in one file and declared in another file) it could get an alignment which is larger than the ABI allows for that type, resulting in aligned moves being used for unaligned loads. For instance, in file A.c: struct S s; In file B.c: struct { // something long }; extern S s; void foo() { struct S p = s; // ... } this copy is a 'memcpy' which is turned into a series of 'movaps' instructions on X86. But this is wrong, because 'struct S' has alignment of 4, not 16. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140902 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp2
-rw-r--r--test/CodeGen/X86/alignment-2.ll26
2 files changed, 28 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index d617d6710c..6a549e8760 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -6537,6 +6537,8 @@ unsigned SelectionDAG::InferPtrAlignment(SDValue Ptr) const {
Align = TD->getPreferredAlignment(GVar);
}
}
+ if (!Align)
+ Align = TLI.getTargetData()->getABITypeAlignment(GV->getType());
}
return MinAlign(Align, GVOffset);
}
diff --git a/test/CodeGen/X86/alignment-2.ll b/test/CodeGen/X86/alignment-2.ll
new file mode 100644
index 0000000000..835cf6275b
--- /dev/null
+++ b/test/CodeGen/X86/alignment-2.ll
@@ -0,0 +1,26 @@
+; RUN: llc < %s -mtriple i386-apple-darwin10 | not grep movaps
+; <rdar://problem/10058036>
+
+%struct._psqlSettings = type { %struct.pg_conn*, i32, %struct.__sFILE*, i8, %struct.printQueryOpt, i8*, i8, i32, %struct.__sFILE*, i8, i32, i8*, i8*, i8*, i64, i8, %struct.__sFILE*, %struct._variable*, i8, i8, i8, i8, i8, i32, i32, i32, i32, i32, i8*, i8*, i8*, i32 }
+%struct.pg_conn = type opaque
+%struct.__sFILE = type { i8*, i32, i32, i16, i16, %struct.__sbuf, i32, i8*, i32 (i8*)*, i32 (i8*, i8*, i32)*, i64 (i8*, i64, i32)*, i32 (i8*, i8*, i32)*, %struct.__sbuf, %struct.__sFILEX*, i32, [3 x i8], [1 x i8], %struct.__sbuf, i32, i64 }
+%struct.__sbuf = type { i8*, i32 }
+%struct.__sFILEX = type opaque
+%struct.printQueryOpt = type { %struct.printTableOpt, i8*, i8, i8*, i8**, i8, i8, i8* }
+%struct.printTableOpt = type { i32, i8, i16, i16, i8, i8, i8, i32, %struct.printTextFormat*, i8*, i8*, i8, i8*, i32, i32, i32 }
+%struct.printTextFormat = type { i8*, [4 x %struct.printTextLineFormat], i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8*, i8 }
+%struct.printTextLineFormat = type { i8*, i8*, i8*, i8* }
+%struct._variable = type { i8*, i8*, void (i8*)*, %struct._variable* }
+%struct.pg_result = type opaque
+
+@pset = external global %struct._psqlSettings
+
+define signext i8 @do_lo_list() nounwind optsize ssp {
+bb:
+ %myopt = alloca %struct.printQueryOpt, align 4
+ %tmp = bitcast %struct.printQueryOpt* %myopt to i8*
+ call void @llvm.memcpy.p0i8.p0i8.i32(i8* %tmp, i8* bitcast (%struct.printQueryOpt* getelementptr inbounds (%struct._psqlSettings* @pset, i32 0, i32 4) to i8*), i32 76, i32 4, i1 false)
+ ret i8 0
+}
+
+declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind