Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ 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; } Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ 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: Index: clang/lib/Basic/TargetInfo.cpp =================================================================== --- clang/lib/Basic/TargetInfo.cpp +++ 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; Index: clang/lib/Basic/Targets/SystemZ.h =================================================================== --- clang/lib/Basic/Targets/SystemZ.h +++ 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; Index: clang/test/CodeGen/SystemZ/align-systemz.c =================================================================== --- clang/test/CodeGen/SystemZ/align-systemz.c +++ 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 - Index: clang/test/CodeGen/SystemZ/systemz-abi.c =================================================================== --- clang/test/CodeGen/SystemZ/systemz-abi.c +++ 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 %{{.*}}) Index: clang/test/CodeGen/SystemZ/zos-alignment.c =================================================================== --- clang/test/CodeGen/SystemZ/zos-alignment.c +++ 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; Index: llvm/test/CodeGen/SystemZ/unaligned-02.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/SystemZ/unaligned-02.ll @@ -0,0 +1,46 @@ +; Check that unaligned accesses of i128 and vector types get the correct alignment added. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 -stop-after=pre-isel-intrinsic-lowering \ +; RUN: | FileCheck %s +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z13 -stop-after=pre-isel-intrinsic-lowering \ +; RUN: -mattr=-vector | FileCheck %s --check-prefix=NO-VX + +; CHECK: target datalayout = "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64" + +define void @f1(ptr %ptr) { +; CHECK: define void @f1(ptr %ptr) #0 { +; CHECK: store i128 0, ptr %ptr, align 8 +; CHECK: store <4 x i32> zeroinitializer, ptr %ptr, align 8 +; CHECK: ret void +; CHECK: } +; NO-VX: define void @f1(ptr %ptr) #0 { +; NO-VX: store i128 0, ptr %ptr, align 8 +; NO-VX: store <4 x i32> zeroinitializer, ptr %ptr, align 16 +; NO-VX: ret void +; NO-VX: } + store i128 0, ptr %ptr + store <4 x i32> zeroinitializer, ptr %ptr + ret void +} + +define void @f2(ptr %ptr) #0 { +; CHECK: define void @f2(ptr %ptr) #1 { +; CHECK: store i128 0, ptr %ptr, align 8 +; CHECK: store <4 x i32> zeroinitializer, ptr %ptr, align 8 +; CHECK: ret void +; CHECK: } +; NO-VX: define void @f2(ptr %ptr) #1 { +; NO-VX: store i128 0, ptr %ptr, align 8 +; NO-VX: store <4 x i32> zeroinitializer, ptr %ptr, align 16 +; NO-VX: ret void +; NO-VX: } + store i128 0, ptr %ptr + store <4 x i32> zeroinitializer, ptr %ptr + ret void +} + +attributes #0 = {"target-features"="-vector"} +; CHECK: attributes #0 = { "target-cpu"="z13" } +; CHECK: attributes #1 = { "target-cpu"="z13" "target-features"="-vector" } +; NO-VX: attributes #0 = { "target-cpu"="z13" "target-features"="-vector" } +; NO-VX: attributes #1 = { "target-cpu"="z13" "target-features"="-vector,-vector" }