asavonic created this revision.
asavonic added reviewers: rjmccall, dmgreen, t.p.northover, ostannard, 
sdesmalen, momchil.velikov, SjoerdMeijer.
Herald added subscribers: mstorsjo, danielkiss, kristof.beyls.
asavonic requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

If a return value is explicitly rounded to 64 bits, an additional
`zext` instruction is emitted, and in some cases it prevents tail call
optimization.

As discussed in D100225 <https://reviews.llvm.org/D100225>, this rounding is 
not necessary and can be
disabled.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100591

Files:
  clang/lib/CodeGen/TargetInfo.cpp
  clang/test/CodeGen/aarch64-varargs.c
  clang/test/CodeGen/arm64-arguments.c
  clang/test/CodeGen/arm64-microsoft-arguments.cpp
  clang/test/CodeGen/attr-noundef.cpp
  clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
  clang/test/CodeGenCXX/trivial_abi.cpp

Index: clang/test/CodeGenCXX/trivial_abi.cpp
===================================================================
--- clang/test/CodeGenCXX/trivial_abi.cpp
+++ clang/test/CodeGenCXX/trivial_abi.cpp
@@ -198,12 +198,11 @@
   testReturnLarge();
 }
 
-// CHECK: define{{.*}} i64 @_Z20testReturnHasTrivialv()
+// CHECK: define{{.*}} i32 @_Z20testReturnHasTrivialv()
 // CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4
 // CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0
 // CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4
-// CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64
-// CHECK: ret i64 %[[COERCE_VAL_II]]
+// CHECK: ret i32 %[[V0]]
 // CHECK: }
 
 Trivial testReturnHasTrivial() {
Index: clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
===================================================================
--- clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
+++ clang/test/CodeGenCXX/microsoft-abi-sret-and-byval.cpp
@@ -87,7 +87,7 @@
 // LINUX-LABEL: define{{.*}} void @_Z12small_returnv(%struct.Small* noalias sret(%struct.Small) align 4 %agg.result)
 // WIN32: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
 // WIN64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
-// WOA64: define dso_local i64 @"?small_return@@YA?AUSmall@@XZ"()
+// WOA64: define dso_local i32 @"?small_return@@YA?AUSmall@@XZ"()
 
 Medium medium_return() { return Medium(); }
 // LINUX-LABEL: define{{.*}} void @_Z13medium_returnv(%struct.Medium* noalias sret(%struct.Medium) align 4 %agg.result)
Index: clang/test/CodeGen/attr-noundef.cpp
===================================================================
--- clang/test/CodeGen/attr-noundef.cpp
+++ clang/test/CodeGen/attr-noundef.cpp
@@ -11,7 +11,7 @@
 Trivial ret_trivial() { return {}; }
 void pass_trivial(Trivial e) {}
 // CHECK-INTEL: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
-// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i64 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE:define( dso_local)?]] i32 @{{.*}}ret_trivial
 // CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
 // CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
 
@@ -43,7 +43,7 @@
 Trivial ret_trivial() { return {}; }
 void pass_trivial(Trivial e) {}
 // CHECK-INTEL: [[DEFINE]] i32 @{{.*}}ret_trivial
-// CHECK-AARCH: [[DEFINE]] i64 @{{.*}}ret_trivial
+// CHECK-AARCH: [[DEFINE]] i32 @{{.*}}ret_trivial
 // CHECK-INTEL: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i32 %
 // CHECK-AARCH: [[DEFINE]] void @{{.*}}pass_trivial{{.*}}(i64 %
 
Index: clang/test/CodeGen/arm64-microsoft-arguments.cpp
===================================================================
--- clang/test/CodeGen/arm64-microsoft-arguments.cpp
+++ clang/test/CodeGen/arm64-microsoft-arguments.cpp
@@ -104,8 +104,8 @@
 
 // Pass and return an object with a non-trivial explicitly defaulted constructor
 // (passed directly, returned directly)
-// CHECK: define {{.*}} i64 @"?f6@@YA?AUS6@@XZ"()
-// CHECK: call i64 {{.*}}func6{{.*}}(i64 {{.*}})
+// CHECK: define {{.*}} i8 @"?f6@@YA?AUS6@@XZ"()
+// CHECK: call i8 {{.*}}func6{{.*}}(i64 {{.*}})
 struct S6a {
   S6a();
 };
@@ -123,8 +123,8 @@
 
 // Pass and return an object with a non-trivial implicitly defaulted constructor
 // (passed directly, returned directly)
-// CHECK: define {{.*}} i64 @"?f7@@YA?AUS7@@XZ"()
-// CHECK: call i64 {{.*}}func7{{.*}}(i64 {{.*}})
+// CHECK: define {{.*}} i8 @"?f7@@YA?AUS7@@XZ"()
+// CHECK: call i8 {{.*}}func7{{.*}}(i64 {{.*}})
 struct S7 {
   S6a x;
 };
Index: clang/test/CodeGen/arm64-arguments.c
===================================================================
--- clang/test/CodeGen/arm64-arguments.c
+++ clang/test/CodeGen/arm64-arguments.c
@@ -5,29 +5,28 @@
   return 0;
 }
 
-// Struct as return type. Aggregates <= 16 bytes are passed directly and round
-// up to multiple of 8 bytes.
-// CHECK: define{{.*}} i64 @f1()
+// Struct as return type. Aggregates <= 16 bytes are passed directly.
+// CHECK: define{{.*}} i8 @f1()
 struct s1 { char f0; };
 struct s1 f1(void) {}
 
-// CHECK: define{{.*}} i64 @f2()
+// CHECK: define{{.*}} i16 @f2()
 struct s2 { short f0; };
 struct s2 f2(void) {}
 
-// CHECK: define{{.*}} i64 @f3()
+// CHECK: define{{.*}} i32 @f3()
 struct s3 { int f0; };
 struct s3 f3(void) {}
 
-// CHECK: define{{.*}} i64 @f4()
+// CHECK: define{{.*}} i32 @f4()
 struct s4 { struct s4_0 { int f0; } f0; };
 struct s4 f4(void) {}
 
-// CHECK: define{{.*}} i64 @f5()
+// CHECK: define{{.*}} i32 @f5()
 struct s5 { struct { } f0; int f1; };
 struct s5 f5(void) {}
 
-// CHECK: define{{.*}} i64 @f6()
+// CHECK: define{{.*}} i32 @f6()
 struct s6 { int f0[1]; };
 struct s6 f6(void) {}
 
@@ -39,19 +38,27 @@
 struct s8 { struct { int : 0; } f0[1]; };
 struct s8 f8(void) {}
 
-// CHECK: define{{.*}} i64 @f9()
+// CHECK: define{{.*}} i32 @f9()
 struct s9 { int f0; int : 0; };
 struct s9 f9(void) {}
 
-// CHECK: define{{.*}} i64 @f10()
+// CHECK: define{{.*}} i32 @f10()
 struct s10 { int f0; int : 0; int : 0; };
 struct s10 f10(void) {}
 
-// CHECK: define{{.*}} i64 @f11()
+// CHECK: define{{.*}} i32 @f11()
 struct s11 { int : 0; int f0; };
 struct s11 f11(void) {}
 
-// CHECK: define{{.*}} i64 @f12()
+// CHECK: define{{.*}} i24 @f11_packed()
+struct s11_packed { char c; short s } __attribute__((packed));
+struct s11_packed f11_packed(void) { }
+
+// CHECK: define{{.*}} i32 @f11_not_packed()
+struct s11_not_packed { char c; short s; };
+struct s11_not_packed f11_not_packed(void) { }
+
+// CHECK: define{{.*}} i32 @f12()
 union u12 { char f0; short f1; int f2; };
 union u12 f12(void) {}
 
@@ -69,28 +76,28 @@
 // CHECK: define{{.*}} void @f16()
 void f16(struct s8 a0) {}
 
-// CHECK: define{{.*}} i64 @f17()
+// CHECK: define{{.*}} i32 @f17()
 struct s17 { short f0 : 13; char f1 : 4; };
 struct s17 f17(void) {}
 
-// CHECK: define{{.*}} i64 @f18()
+// CHECK: define{{.*}} i32 @f18()
 struct s18 { short f0; char f1 : 4; };
 struct s18 f18(void) {}
 
-// CHECK: define{{.*}} i64 @f19()
+// CHECK: define{{.*}} i32 @f19()
 struct s19 { int f0; struct s8 f1; };
 struct s19 f19(void) {}
 
-// CHECK: define{{.*}} i64 @f20()
+// CHECK: define{{.*}} i32 @f20()
 struct s20 { struct s8 f1; int f0; };
 struct s20 f20(void) {}
 
-// CHECK: define{{.*}} i64 @f21()
+// CHECK: define{{.*}} i32 @f21()
 struct s21 { struct {} f1; int f0 : 4; };
 struct s21 f21(void) {}
 
-// CHECK: define{{.*}} i64 @f22()
-// CHECK: define{{.*}} i64 @f23()
+// CHECK: define{{.*}} i16 @f22()
+// CHECK: define{{.*}} i32 @f23()
 // CHECK: define{{.*}} i64 @f24()
 // CHECK: define{{.*}} [2 x i64] @f25()
 // CHECK: define{{.*}} { float, float } @f26()
@@ -102,11 +109,11 @@
 _Complex float      f26(void) {}
 _Complex double     f27(void) {}
 
-// CHECK: define{{.*}} i64 @f28()
+// CHECK: define{{.*}} i16 @f28()
 struct s28 { _Complex char f0; };
 struct s28 f28() {}
 
-// CHECK: define{{.*}} i64 @f29()
+// CHECK: define{{.*}} i32 @f29()
 struct s29 { _Complex short f0; };
 struct s29 f29() {}
 
Index: clang/test/CodeGen/aarch64-varargs.c
===================================================================
--- clang/test/CodeGen/aarch64-varargs.c
+++ clang/test/CodeGen/aarch64-varargs.c
@@ -473,7 +473,7 @@
   int val;
 } underaligned_int_struct;
 underaligned_int_struct underaligned_int_struct_test() {
-// CHECK-LABEL: define{{.*}} i64 @underaligned_int_struct_test()
+// CHECK-LABEL: define{{.*}} i32 @underaligned_int_struct_test()
   return va_arg(the_list, underaligned_int_struct);
 // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
 // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
@@ -675,7 +675,7 @@
   int val __attribute__((packed,aligned(2)));
 } underaligned_int_struct_member;
 underaligned_int_struct_member underaligned_int_struct_member_test() {
-// CHECK-LABEL: define{{.*}} i64 @underaligned_int_struct_member_test()
+// CHECK-LABEL: define{{.*}} i32 @underaligned_int_struct_member_test()
   return va_arg(the_list, underaligned_int_struct_member);
 // CHECK: [[GR_OFFS:%[a-z_0-9]+]] = load i32, i32* getelementptr inbounds (%struct.__va_list, %struct.__va_list* @the_list, i32 0, i32 3)
 // CHECK: [[EARLY_ONSTACK:%[a-z_0-9]+]] = icmp sge i32 [[GR_OFFS]], 0
Index: clang/lib/CodeGen/TargetInfo.cpp
===================================================================
--- clang/lib/CodeGen/TargetInfo.cpp
+++ clang/lib/CodeGen/TargetInfo.cpp
@@ -5753,6 +5753,12 @@
     if (getTarget().isRenderScriptTarget()) {
       return coerceToIntArray(RetTy, getContext(), getVMContext());
     }
+
+    if (Size <= 64) {
+      return ABIArgInfo::getDirect(
+          llvm::IntegerType::get(getVMContext(), Size));
+    }
+
     unsigned Alignment = getContext().getTypeAlign(RetTy);
     Size = llvm::alignTo(Size, 64); // round up to multiple of 8 bytes
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to