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

via flang-commits flang-commits at lists.llvm.org
Tue Nov 19 03:58:24 PST 2024


Author: Zhaoxin Yang
Date: 2024-11-19T19:58:20+08:00
New Revision: b24acc06e1d465b3e3e4e28515dd437f6a7454f2

URL: https://github.com/llvm/llvm-project/commit/b24acc06e1d465b3e3e4e28515dd437f6a7454f2
DIFF: https://github.com/llvm/llvm-project/commit/b24acc06e1d465b3e3e4e28515dd437f6a7454f2.diff

LOG: [Flang][LoongArch] Add sign extension for i32 arguments and returns in function signatures. (#116146)

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://github.com/loongson/la-abi-specs/blob/release/lapcs.adoc#Fundamental-types

Added: 
    flang/test/Fir/target-rewrite-integer-loongarch64.fir

Modified: 
    flang/lib/Optimizer/CodeGen/Target.cpp

Removed: 
    


################################################################################
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..8421cbbb41a9d3
--- /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
+}


        


More information about the flang-commits mailing list