Skip to content

Conversation

@kito-cheng
Copy link
Member

@kito-cheng kito-cheng commented Feb 10, 2025

…argetMachine

RISC-V's data layout is determined by the ABI, not just the target triple. However, the TargetMachine is created using the data layout from the target triple, which is not always correct. This patch uses the target ABI from the module and passes it to the TargetMachine, ensuring that the data layout is set correctly according to the ABI.

The same problem will happen with other targets like MIPS, but unfortunately, MIPS didn't emit the target-abi into the module flags, so this patch only fixes the issue for RISC-V.

NOTE: MIPS with -mabi=n32 can trigger the same issue.

Another possible solution is add new parameter to the TargetMachine constructor, but that would require changes in all the targets.

@llvmbot llvmbot added lld lld:ELF LTO Link time optimization (regular/full LTO or ThinLTO) labels Feb 10, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 10, 2025

@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-lld
@llvm/pr-subscribers-lto

@llvm/pr-subscribers-lld-elf

Author: Kito Cheng (kito-cheng)

Changes

…argetMachine

RISC-V's data layout is also determined by the ABI, not only the target triple, however the TargetMachine is created with the target triple's data layout, that is not always correct. This patch changes the TargetMachine's data layout to the one specified in the module flags if present.

The same problem will happen with other targets like MIPS, but unfortunately, MIPS didn't emit the target-abi into the module flags, so this patch only fixes the issue for RISC-V.

NOTE: MIPS with -mabi=n32 can trigger the same issue.

Another possible solution is add new parameter to the TargetMachine constructor, but that would require changes in all the targets.


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

2 Files Affected:

  • (added) lld/test/ELF/lto/riscv-ilp32e.ll (+25)
  • (modified) llvm/lib/LTO/LTOBackend.cpp (+11-1)
diff --git a/lld/test/ELF/lto/riscv-ilp32e.ll b/lld/test/ELF/lto/riscv-ilp32e.ll
new file mode 100644
index 000000000000000..ea2b57d48335865
--- /dev/null
+++ b/lld/test/ELF/lto/riscv-ilp32e.ll
@@ -0,0 +1,25 @@
+; REQUIRES: riscv
+;
+; Check that we don't crash on DataLayout incompatibility issue.
+;
+; RUN: llvm-as %s -o %t.o
+; RUN: ld.lld %t.o -o %t.elf
+; RUN: llvm-readobj -h %t.elf | FileCheck %s --check-prefixes=CHECK
+;
+; CHECK:  Machine: EM_RISCV (0xF3)
+; CHECK:  EF_RISCV_RVE (0x8)
+
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32-S32"
+target triple = "riscv32-unknown-unknown-elf"
+
+define dso_local i32 @_start() #0 {
+entry:
+  ret i32 0
+}
+
+attributes #0 = { "target-cpu"="generic-rv32" "target-features"="+32bit,+e" }
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 1, !"target-abi", !"ilp32e"}
diff --git a/llvm/lib/LTO/LTOBackend.cpp b/llvm/lib/LTO/LTOBackend.cpp
index 8a2dddce4892c1a..b9d2242d4a2cf46 100644
--- a/llvm/lib/LTO/LTOBackend.cpp
+++ b/llvm/lib/LTO/LTOBackend.cpp
@@ -221,8 +221,18 @@ createTargetMachine(const Config &Conf, const Target *TheTarget, Module &M) {
   else
     CodeModel = M.getCodeModel();
 
+  TargetOptions TargetOpts = Conf.Options;
+
+  if (TargetOpts.MCOptions.ABIName.empty()) {
+    Metadata *ABI = M.getModuleFlag("target-abi");
+    if (ABI) {
+      const StringRef &ModABI = cast<MDString>(ABI)->getString();
+      TargetOpts.MCOptions.ABIName = ModABI;
+    }
+  }
+
   std::unique_ptr<TargetMachine> TM(TheTarget->createTargetMachine(
-      TheTriple, Conf.CPU, Features.getString(), Conf.Options, RelocModel,
+      TheTriple, Conf.CPU, Features.getString(), TargetOpts, RelocModel,
       CodeModel, Conf.CGOptLevel));
 
   assert(TM && "Failed to create target machine");

Copy link
Contributor

@teresajohnson teresajohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this isn't an lld change, the test should be in LLVM not lld. Take a look at llvm/test/LTO/X86/codemodel-1.ll for an example, and the LTO subdirectory presumably needs a RISCV subdirectory.

@kito-cheng
Copy link
Member Author

Changes:

  • Move test file from lld/test/ELF/lto to llvm/test/LTO/RISCV

@lenary
Copy link
Member

lenary commented Feb 12, 2025

I read the description here, and was a little concerned, but on reading the code I'm not.

This patch changes the TargetMachine's data layout to the one specified in the module flags if present.

This sentence concerned me, but reading the implementation, it isn't quite what's happening. Instead, you're providing the target-abi module flag as a TMOption only if the -target-abi argument hasn't been specified at the command line, which in LTO is very unlikely.

Not only is the existing datalayout logic unaffected, but i think this now brings how target-abi is handled inline with how datalayout is handled:

  • first use the arguments
  • then use whatever is in the LLVM IR (was skipped before for the ABI, not for the datalayout)
  • then use a fallback/default

It would be good to update the message when this lands to clarify this, as my first reading did have me concerned we didn't follow this logic which could have affected a lot of tests and other users of serialised LLVM IR.

Another possible solution is add new parameter to the TargetMachine constructor, but that would require changes in all the targets.

I looked at this a while ago (iirc for the same problem) and it's really really messy to fix. We should do it sometime, but I recognise we cannot do it quickly. This is a better step for right now.

@asb
Copy link
Contributor

asb commented Feb 17, 2025

@kito-cheng I'd mentioned in the last RISC-V sync-up call that I was seeing warnings when linking e.g. SPEC in the llvm-test-suite and Sam mentioned this patch. I was wondering to what degree there are known issues you're tracking (and if there is a bug report for this?). Trialling this patch, I actually see more warnings emitted when linking spec 2017. (Obviously, that doesn't necessarily indicate a problem with the patch - we could just be surfacing more underlying issues). Is this expected?

(EDIT: It's not immediately obvious to me why this patch results in more warnings than before, but I assume the warnings are #69780 and perhaps fixed by #100833)

Before:

[4955/4968] Linking CXX executable External/SPEC/CFP2017rate/511.povray_r/511.povray_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4956/4968] Linking CXX executable External/SPEC/CINT2017speed/620.omnetpp_s/620.omnetpp_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4957/4968] Linking CXX executable External/SPEC/CINT2017rate/520.omnetpp_r/520.omnetpp_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4962/4968] Linking C executable External/SPEC/CINT2017speed/600.perlbench_s/600.perlbench_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4963/4968] Linking C executable External/SPEC/CINT2017rate/500.perlbench_r/500.perlbench_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4964/4968] Linking CXX executable External/SPEC/CINT2017rate/523.xalancbmk_r/523.xalancbmk_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4965/4968] Linking CXX executable External/SPEC/CINT2017speed/623.xalancbmk_s/623.xalancbmk_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4968/4968] Linking CXX executable External/SPEC/CFP2017rate/526.blender_r/526.blender_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)

After:

[4909/4968] Linking CXX executable tools/not
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4938/4968] Linking CXX executable External/SPEC/CINT2017rate/541.leela_r/541.leela_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4939/4968] Linking CXX executable External/SPEC/CINT2017speed/641.leela_s/641.leela_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4952/4968] Linking CXX executable External/SPEC/CFP2017rate/508.namd_r/508.namd_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4955/4968] Linking CXX executable External/SPEC/CINT2017rate/520.omnetpp_r/520.omnetpp_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4956/4968] Linking CXX executable External/SPEC/CFP2017rate/511.povray_r/511.povray_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4957/4968] Linking CXX executable External/SPEC/CINT2017speed/620.omnetpp_s/620.omnetpp_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4961/4968] Linking CXX executable External/SPEC/CFP2017rate/510.parest_r/510.parest_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4962/4968] Linking C executable External/SPEC/CINT2017rate/500.perlbench_r/500.perlbench_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4963/4968] Linking C executable External/SPEC/CINT2017speed/600.perlbench_s/600.perlbench_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4964/4968] Linking CXX executable External/SPEC/CINT2017speed/623.xalancbmk_s/623.xalancbmk_s
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4965/4968] Linking CXX executable External/SPEC/CINT2017rate/523.xalancbmk_r/523.xalancbmk_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
[4967/4968] Linking C executable External/SPEC/CINT2017rate/502.gcc_r/502.gcc_r
[4968/4968] Linking CXX executable External/SPEC/CFP2017rate/526.blender_r/526.blender_r
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)
Hard-float 'd' ABI can't be used for a target that doesn't support the D instruction set extension (ignoring target-abi)

Build config:

CONF=clang-head-lto
CLANG_BIN_DIR=$HOME/llvm-project/build/release/bin
CFLAGS="-march=rv64gc -flto"
cat - <<EOF > $CONF.cmake
set(CMAKE_SYSTEM_NAME Linux)

set(CMAKE_SYSROOT $HOME/rvsysroot)

set(CMAKE_C_COMPILER $CLANG_BIN_DIR/clang)
set(CMAKE_CXX_COMPILER $CLANG_BIN_DIR/clang++)

set(CMAKE_C_COMPILER_TARGET riscv64-linux-gnu)
set(CMAKE_CXX_COMPILER_TARGET riscv64-linux-gnu)
set(CMAKE_C_FLAGS_INIT "$CFLAGS")
set(CMAKE_CXX_FLAGS_INIT "$CFLAGS")

set(CMAKE_LINKER_TYPE LLD)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
EOF
cmake -G Ninja \
  -B build.$CONF \
  --toolchain=$CONF.cmake \
  -DTEST_SUITE_SPEC2017_ROOT=~/cpu2017 \
  -DTEST_SUITE_SUBDIRS=External/SPEC \
  -DTEST_SUITE_COLLECT_CODE_SIZE=OFF \
  -DTEST_SUITE_COLLECT_COMPILE_TIME=OFF
cmake --build build.$CONF

@kito-cheng
Copy link
Member Author

@lenary comment updated, it should look like more reasonable :P

@kito-cheng
Copy link
Member Author

@asb the problem I try to resolve is the LTO is not work at all with ilp32e since this issue...and #100833 may able to fix your issue, although I feel that may not right way to fix your issue even it can help... I could try to reproduce your issue on my hand and see how to improve that

@asb
Copy link
Contributor

asb commented Feb 18, 2025

@asb the problem I try to resolve is the LTO is not work at all with ilp32e since this issue...and #100833 may able to fix your issue, although I feel that may not right way to fix your issue even it can help... I could try to reproduce your issue on my hand and see how to improve that

I poked at it a bit more and added a comment here with a reproducer, as it seems that issue is acting as a meta-bug of sorts. If you have thoughts on this it would be very welcome.

So although this PR is nothing to do with that problem I isolated, I'll note again that it does result in additional warnings when building the llvm-test-suite vs before it was applied - so I wonder if that's expected?

@kito-cheng
Copy link
Member Author

@asb my best guess from the Craig's PR (#127760) is we setting the ABI right in more place, and then expose more potential issue on that issue, does that Craig's fix remove all those warning message now? Let me know if still appeared :)

@topperc
Copy link
Collaborator

topperc commented Feb 27, 2025

Looks like #100833 has been closed without commit for now.

@llvmbot llvmbot added the llvm:ir label Mar 3, 2025
Copy link
Member

@lenary lenary left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I'm happy with this.

@MaskRay MaskRay changed the title [LTO] Override TargetABI from module flags if present when creating T… [LTO] Override TargetABI from module flags if present when creating TargetMachine Mar 4, 2025
Copy link
Contributor

@teresajohnson teresajohnson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm once the existing suggestions from other reviewers are resolved

…argetMachine

RISC-V's data layout is also determined by the ABI, not only the target triple,
however the TargetMachine is created with the target triple's data layout,
that is not always correct. This patch changes the TargetMachine's data
layout to the one specified in the module flags if present.

The same problem will happen with other targets like MIPS, but unfortunately,
MIPS didn't emit the target-abi into the module flags, so this patch only
fixes the issue for RISC-V.

NOTE: MIPS with -mabi=n32 can trigger the same issue.

Another possible solution is add new parameter to the TargetMachine
constructor, but that would require changes in all the targets.
@kito-cheng kito-cheng force-pushed the kitoc/fix-lto-datalayout-computation branch from d747098 to 1d61381 Compare March 7, 2025 03:48
Co-authored-by: Alexander Richardson <[email protected]>
@kito-cheng kito-cheng merged commit 733ad3f into llvm:main Mar 7, 2025
9 of 10 checks passed
@kito-cheng kito-cheng deleted the kitoc/fix-lto-datalayout-computation branch March 10, 2025 13:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend:RISC-V lld:ELF lld llvm:ir LTO Link time optimization (regular/full LTO or ThinLTO)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants