[flang-commits] [flang] [Flang][LoongArch] Add sign extension for i32 arguments and returns in function signatures. (PR #116146)

Zhaoxin Yang via flang-commits flang-commits at lists.llvm.org
Mon Nov 18 00:59:31 PST 2024


https://github.com/ylzsx updated https://github.com/llvm/llvm-project/pull/116146

>From 714af00296a9c4439c6d2d34a3e63fba296fa1d6 Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Mon, 11 Nov 2024 19:39:18 +0800
Subject: [PATCH 1/2] [Flang][LoongArch] Add sign extension for i32 arguments
 and returns in function signatures.

In loongarch64 LP64D ABI, `unsigned 32-bit` types, such as unsigned int,
are stored in general-purpose registers as proper sign extensions of their
32-bit values. Therefore, Flang also follows it if a function needs to be
interoperable with C.

Reference:
https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_abi_lp64d
---
 flang/lib/Optimizer/CodeGen/Target.cpp        | 24 +++++++++++++++++
 .../target-rewrite-integer-loongarch64.fir    | 27 +++++++++++++++++++
 2 files changed, 51 insertions(+)
 create mode 100644 flang/test/Fir/target-rewrite-integer-loongarch64.fir

diff --git a/flang/lib/Optimizer/CodeGen/Target.cpp b/flang/lib/Optimizer/CodeGen/Target.cpp
index 5f746bf80e9d5b..9ec055b1aecabb 100644
--- a/flang/lib/Optimizer/CodeGen/Target.cpp
+++ b/flang/lib/Optimizer/CodeGen/Target.cpp
@@ -1127,6 +1127,30 @@ struct TargetLoongArch64 : public GenericTarget<TargetLoongArch64> {
     }
     return marshal;
   }
+
+  CodeGenSpecifics::Marshalling
+  integerArgumentType(mlir::Location loc,
+                      mlir::IntegerType argTy) const override {
+    if (argTy.getWidth() == 32) {
+      // LA64 LP64D ABI requires unsigned 32 bit integers to be sign extended.
+      // Therefore, Flang also follows it if a function needs to be
+      // interoperable with C.
+      //
+      // Currently, it only adds `signext` attribute to the dummy arguments and
+      // return values in the function signatures, but it does not add the
+      // corresponding attribute to the actual arguments and return values in
+      // `fir.call` instruction. Thanks to LLVM's integration of all these
+      // attributes, the modification is still effective.
+      CodeGenSpecifics::Marshalling marshal;
+      AT::IntegerExtension intExt = AT::IntegerExtension::Sign;
+      marshal.emplace_back(argTy, AT{/*alignment=*/0, /*byval=*/false,
+                                     /*sret=*/false, /*append=*/false,
+                                     /*intExt=*/intExt});
+      return marshal;
+    }
+
+    return GenericTarget::integerArgumentType(loc, argTy);
+  }
 };
 } // namespace
 
diff --git a/flang/test/Fir/target-rewrite-integer-loongarch64.fir b/flang/test/Fir/target-rewrite-integer-loongarch64.fir
new file mode 100644
index 00000000000000..e48673afb2b019
--- /dev/null
+++ b/flang/test/Fir/target-rewrite-integer-loongarch64.fir
@@ -0,0 +1,27 @@
+// Test i32 passing and returning on LoongArch64
+// LoongArch64 LP64D ABI requires unsigned 32 bit integers to be sign extended.
+//
+// REQUIRES: loongarch-registered-target
+// RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64
+// RUN: tco -target="loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64_LLVM
+
+// LOONGARCH64: func.func private @cfunc32(i32 {llvm.signext}) -> (i32 {llvm.signext}) attributes {fir.bindc_name = "cfunc32"}
+
+// LOONGARCH64_LLVM: declare signext i32 @cfunc32(i32 signext)
+func.func private @cfunc32(i32) -> i32 attributes {fir.bindc_name = "cfunc32"}
+
+// LOONGARCH64-LABEL: func.func @foo(
+// LOONGARCH64-SAME: %[[VAL_0:.*]]: i32 {llvm.signext}) -> (i32 {llvm.signext}) attributes {fir.bindc_name = "foo"} {
+// LOONGARCH64: %[[VAL_1:.*]] = fir.call @cfunc32(%[[VAL_0]]) fastmath<contract> : (i32) -> i32
+// LOONGARCH64: return %[[VAL_1]] : i32
+// LOONGARCH64: }
+
+// LOONGARCH64_LLVM-LABEL: define signext i32 @foo(
+// LOONGARCH64_LLVM: i32 signext %[[VAL_0:.*]]) {
+// LOONGARCH64_LLVM: %[[VAL_1:.*]] = call i32 @cfunc32(i32 %[[VAL_0]])
+// LOONGARCH64_LLVM: ret i32 %[[VAL_1]]
+// LOONGARCH64_LLVM: }
+func.func @foo(%0: i32) -> i32 attributes {fir.bindc_name = "foo"} {
+    %1 = fir.call @cfunc32(%0) fastmath<contract> : (i32) -> i32
+    return %1 : i32
+}

>From 56f64ed12967283e3ee0078805d2efd696c1544c Mon Sep 17 00:00:00 2001
From: yangzhaoxin <yangzhaoxin at loongson.cn>
Date: Mon, 18 Nov 2024 16:53:31 +0800
Subject: [PATCH 2/2] Modify comments. NFC

---
 flang/test/Fir/target-rewrite-integer-loongarch64.fir | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/flang/test/Fir/target-rewrite-integer-loongarch64.fir b/flang/test/Fir/target-rewrite-integer-loongarch64.fir
index e48673afb2b019..6fe97ec92fa549 100644
--- a/flang/test/Fir/target-rewrite-integer-loongarch64.fir
+++ b/flang/test/Fir/target-rewrite-integer-loongarch64.fir
@@ -1,6 +1,6 @@
-// Test i32 passing and returning on LoongArch64
-// LoongArch64 LP64D ABI requires unsigned 32 bit integers to be sign extended.
-//
+/// Test i32 passing and returning on LoongArch64
+/// LoongArch64 LP64D ABI requires unsigned 32 bit integers to be sign extended.
+
 // REQUIRES: loongarch-registered-target
 // RUN: fir-opt --target-rewrite="target=loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64
 // RUN: tco -target="loongarch64-unknown-linux-gnu" %s | FileCheck %s --check-prefix=LOONGARCH64_LLVM



More information about the flang-commits mailing list