diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -78,6 +78,7 @@ unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; + unsigned char Int128Align; // Fixed point bit widths unsigned char ShortAccumWidth, ShortAccumAlign; @@ -470,6 +471,9 @@ unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } + /// getInt128Align() - Returns the alignment of Int128. + unsigned getInt128Align() const { return Int128Align; } + /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and /// 'unsigned short _Accum' for this target, in bits. unsigned getShortAccumWidth() const { return ShortAccumWidth; } diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -2082,7 +2082,7 @@ case BuiltinType::Int128: case BuiltinType::UInt128: Width = 128; - Align = 128; // int128_t is 128-bit aligned on all targets. + Align = Target->getInt128Align(); break; case BuiltinType::ShortAccum: case BuiltinType::UShortAccum: diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp --- a/clang/lib/Basic/TargetInfo.cpp +++ b/clang/lib/Basic/TargetInfo.cpp @@ -45,6 +45,7 @@ IntWidth = IntAlign = 32; LongWidth = LongAlign = 32; LongLongWidth = LongLongAlign = 64; + Int128Align = 128; // Fixed point default bit widths ShortAccumWidth = ShortAccumAlign = 16; diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h --- a/clang/lib/Basic/Targets/SystemZ.h +++ b/clang/lib/Basic/Targets/SystemZ.h @@ -40,6 +40,7 @@ TLSSupported = true; IntWidth = IntAlign = 32; LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64; + Int128Align = 64; PointerWidth = PointerAlign = 64; LongDoubleWidth = 128; LongDoubleAlign = 64; diff --git a/clang/test/CodeGen/SystemZ/align-systemz.c b/clang/test/CodeGen/SystemZ/align-systemz.c --- a/clang/test/CodeGen/SystemZ/align-systemz.c +++ b/clang/test/CodeGen/SystemZ/align-systemz.c @@ -26,6 +26,14 @@ } +// The SystemZ ABI aligns __int128_t to only eight bytes. + +struct S_int128 { __int128_t B; } Obj_I128; +__int128_t GlobI128; +// CHECK: @Obj_I128 = global %struct.S_int128 zeroinitializer, align 8 +// CHECK: @GlobI128 = global i128 0, align 8 + + // Alignment should be respected for coerced argument loads struct arg { long y __attribute__((packed, aligned(4))); }; @@ -40,4 +48,3 @@ // CHECK-LABEL: @test // CHECK: load i64, i64* getelementptr inbounds (%struct.arg, %struct.arg* @x, i32 0, i32 0), align 4 - diff --git a/clang/test/CodeGen/SystemZ/systemz-abi.c b/clang/test/CodeGen/SystemZ/systemz-abi.c --- a/clang/test/CodeGen/SystemZ/systemz-abi.c +++ b/clang/test/CodeGen/SystemZ/systemz-abi.c @@ -43,7 +43,7 @@ // CHECK-LABEL: define{{.*}} i64 @pass_longlong(i64 %{{.*}}) __int128 pass_int128(__int128 arg) { return arg; } -// CHECK-LABEL: define{{.*}} void @pass_int128(i128* noalias sret(i128) align 16 %{{.*}}, i128* %0) +// CHECK-LABEL: define{{.*}} void @pass_int128(i128* noalias sret(i128) align 8 %{{.*}}, i128* %0) float pass_float(float arg) { return arg; } // CHECK-LABEL: define{{.*}} float @pass_float(float %{{.*}}) diff --git a/clang/test/CodeGen/SystemZ/zos-alignment.c b/clang/test/CodeGen/SystemZ/zos-alignment.c --- a/clang/test/CodeGen/SystemZ/zos-alignment.c +++ b/clang/test/CodeGen/SystemZ/zos-alignment.c @@ -160,6 +160,13 @@ // CHECK-NEXT: 8 | char b // CHECK-NEXT: | [sizeof=16, align=8] +struct s12 { + __int128_t a; +} S12; +// CHECK: 0 | struct s12 +// CHECK-NEXT: 0 | __int128_t a +// CHECK-NEXT: | [sizeof=16, align=8] + union u0 { unsigned short d1 __attribute__((packed)); int d2 : 10; diff --git a/llvm/test/CodeGen/SystemZ/unaligned-02.ll b/llvm/test/CodeGen/SystemZ/unaligned-02.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/unaligned-02.ll @@ -0,0 +1,13 @@ +; Check that an unaligned i128 access get the correct alignment added. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -stop-after=pre-isel-intrinsic-lowering \ +; RUN: | FileCheck %s + +define void @f1(ptr %ptr) { +; CHECK: define void @f1(ptr %ptr) { +; CHECK-NEXT: store i128 0, ptr %ptr, align 8 +; CHECK-NEXT: ret void +; CHECK-NEXT: } + store i128 0, ptr %ptr + ret void +}