llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Folkert de Vries (folkertdev)

<details>
<summary>Changes</summary>

fixes https://github.com/llvm/llvm-project/issues/213541

On `mips64` and `mips64el`, an `i128` needs to be register-aligned to an 
even-numbered register to be compatible with GCC. Insert padding to make that 
true.

GCC applies the additional alignment here:

https://github.com/gcc-mirror/gcc/blob/529304e456c9be38139325e3c2567f7d2a93e7c8/gcc/config/mips/mips.cc#L6210-L6223

---
Full diff: https://github.com/llvm/llvm-project/pull/214322.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.md (+3) 
- (modified) clang/lib/CodeGen/Targets/Mips.cpp (+14-7) 
- (modified) clang/test/CodeGen/mips64-padding-arg.c (+41) 


``````````diff
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index d4b1cf9e44945..3e6397ae5707b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -85,6 +85,9 @@ features cannot lower the translation-unit ABI level;
   always passed the parts separately. `-fclang-abi-compat=23` restores the 
previous
   behavior. (#GH212109)
 
+- On MIPS N32/N64, an `__int128` now correctly start in an even-numbered 
register
+  or 16-byte aligned stack slot, matching GCC.
+
 ### AST Dumping Potentially Breaking Changes
 
 ### Clang Frontend Potentially Breaking Changes
diff --git a/clang/lib/CodeGen/Targets/Mips.cpp 
b/clang/lib/CodeGen/Targets/Mips.cpp
index c093cfc668c2e..90d1b5e5dcb20 100644
--- a/clang/lib/CodeGen/Targets/Mips.cpp
+++ b/clang/lib/CodeGen/Targets/Mips.cpp
@@ -49,7 +49,7 @@ class MipsABIInfo : public ABIInfo {
   void computeInfo(CGFunctionInfo &FI) const override;
   RValue EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty,
                    AggValueSlot Slot) const override;
-  ABIArgInfo extendType(QualType Ty) const;
+  ABIArgInfo extendType(QualType Ty, llvm::Type *Padding = nullptr) const;
 };
 
 class MIPSTargetCodeGenInfo : public TargetCodeGenInfo {
@@ -292,12 +292,19 @@ MipsABIInfo::classifyArgumentType(QualType Ty, uint64_t 
&Offset) const {
          !getContext().getTargetInfo().hasInt128Type()))
       return getNaturalAlignIndirect(Ty, getDataLayout().getAllocaAddrSpace());
 
+  // Scalars never get explicit padding on O32: CC_MipsO32 already does the
+  // alignment itself based on the argument's original alignment.
+  //
+  // For __int128 and other types that are 16-byte aligned this padding ensures
+  // that the value starts in an even-numbered register or stack slot.
+  llvm::Type *Padding =
+      IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset);
+
   // All integral types are promoted to the GPR width.
   if (Ty->isIntegralOrEnumerationType())
-    return extendType(Ty);
+    return extendType(Ty, Padding);
 
-  return ABIArgInfo::getDirect(
-      nullptr, 0, IsO32 ? nullptr : getPaddingType(OrigOffset, CurrOffset));
+  return ABIArgInfo::getDirect(nullptr, 0, Padding);
 }
 
 llvm::Type*
@@ -468,14 +475,14 @@ RValue MipsABIInfo::EmitVAArg(CodeGenFunction &CGF, 
Address VAListAddr,
   return Res;
 }
 
-ABIArgInfo MipsABIInfo::extendType(QualType Ty) const {
+ABIArgInfo MipsABIInfo::extendType(QualType Ty, llvm::Type *Padding) const {
   int TySize = getContext().getTypeSize(Ty);
 
   // MIPS64 ABI requires unsigned 32 bit integers to be sign extended.
   if (Ty->isUnsignedIntegerOrEnumerationType() && TySize == 32)
-    return ABIArgInfo::getSignExtend(Ty);
+    return ABIArgInfo::getSignExtend(Ty, /*T=*/nullptr, Padding);
 
-  return ABIArgInfo::getExtend(Ty);
+  return ABIArgInfo::getExtend(Ty, /*T=*/nullptr, Padding);
 }
 
 bool
diff --git a/clang/test/CodeGen/mips64-padding-arg.c 
b/clang/test/CodeGen/mips64-padding-arg.c
index bb92a841c3f61..e2078c9294a0b 100644
--- a/clang/test/CodeGen/mips64-padding-arg.c
+++ b/clang/test/CodeGen/mips64-padding-arg.c
@@ -43,6 +43,47 @@ S0 foo5(long double a0) {
   return foo6(1, 2, a0);
 }
 
+#ifdef __SIZEOF_INT128__
+// Insert padding before a 128-bit integer argument, which is 16-byte aligned, 
to make it start in an even-numbered register.
+//
+// N64-LABEL: define{{.*}} void @foo11(i32 noundef signext %a0, i64 %0, i128 
noundef signext %a1)
+// N64: tail call void @foo12(i32 noundef signext 1, i32 noundef signext 2, 
i32 noundef signext %a0, i64 undef, i128 noundef signext %a1)
+// N64: declare void @foo12(i32 noundef signext, i32 noundef signext, i32 
noundef signext, i64, i128 noundef signext)
+
+extern void foo12(int, int, int, __int128);
+
+void foo11(int a0, __int128 a1) {
+  foo12(1, 2, a0, a1);
+}
+
+// Do not insert padding if the 128-bit integer is already 16-byte aligned.
+// Hence foo13 needs padding but foo14 does not.
+//
+// N64-LABEL: define{{.*}} void @foo13(i32 noundef signext %a0, i64 %0, i128 
noundef zeroext %a1)
+// N64: tail call void @foo14(i32 noundef signext 1, i32 noundef signext %a0, 
i128 noundef zeroext %a1)
+// N64: declare void @foo14(i32 noundef signext, i32 noundef signext, i128 
noundef zeroext)
+
+extern void foo14(int, int, unsigned __int128);
+
+void foo13(int a0, unsigned __int128 a1) {
+  foo14(1, a0, a1);
+}
+
+// Test a case where all but one argument register is exhausted.
+// The padding is still inserted, and the full __int128 value is
+// passed via the stack, it is not split.
+//
+// N64-LABEL: define{{.*}} void @foo15(i64 noundef signext %a0, i64 noundef 
signext %a1, i64 noundef signext %a2, i64 noundef signext %a3, i64 noundef 
signext %a4, i64 noundef signext %a5, i64 noundef signext %a6, i64 %0, i128 
noundef signext %a7)
+// N64: tail call void @foo16(i64 noundef signext %a0, i64 noundef signext 
%a1, i64 noundef signext %a2, i64 noundef signext %a3, i64 noundef signext %a4, 
i64 noundef signext %a5, i64 noundef signext %a6, i64 undef, i128 noundef 
signext %a7)
+// N64: declare void @foo16(i64 noundef signext, i64 noundef signext, i64 
noundef signext, i64 noundef signext, i64 noundef signext, i64 noundef signext, 
i64 noundef signext, i64, i128 noundef signext)
+
+extern void foo16(long, long, long, long, long, long, long, __int128);
+
+void foo15(long a0, long a1, long a2, long a3, long a4, long a5, long a6, 
__int128 a7) {
+  foo16(a0, a1, a2, a3, a4, a5, a6, a7);
+}
+#endif
+
 // Do not insert padding if ABI is O32.
 //
 // O32-LABEL: define{{.*}} void @foo7(float noundef %a0, double noundef %a1)

``````````

</details>


https://github.com/llvm/llvm-project/pull/214322
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to