[RISCV] Allow mismatched SmallDataLimit and use Min for conflicting values
authorFangrui Song <i@maskray.me>
Wed, 8 Feb 2023 01:13:21 +0000 (17:13 -0800)
committerFangrui Song <i@maskray.me>
Wed, 8 Feb 2023 01:13:21 +0000 (17:13 -0800)
Fix an issue about module linking with LTO.

When compiling with PIE, the small data limitation needs to be consistent with that in PIC, otherwise there will be linking errors due to conflicting values.

bar.c
```
int bar() { return 1; }
```

foo.c
```
int foo() { return 1; }
```

```
clang --target=riscv64-unknown-linux-gnu -flto -c foo.c -o foo.o -fPIE
clang --target=riscv64-unknown-linux-gnu -flto -c bar.c -o bar.o -fPIC

clang --target=riscv64-unknown-linux-gnu -flto foo.o bar.o -flto -nostdlib -v -fuse-ld=lld
```

```
ld.lld: error: linking module flags 'SmallDataLimit': IDs have conflicting values in 'bar.o' and 'ld-temp.o'
clang-15: error: linker command failed with exit code 1 (use -v to see invocation)
```

Use Min instead of Error for conflicting SmallDataLimit.

Authored by: @joshua-arch1
Signed-off-by: xiaojing.zhang <xiaojing.zhang@xcalibyte.com>
Signed-off-by: jianxin.lai <jianxin.lai@xcalibyte.com>
Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D131230

clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/RISCV/riscv-sdata-module-flag.c
clang/test/CodeGen/RISCV/rvv-intrinsics-handcrafted/vlenb.c
llvm/test/CodeGen/RISCV/sdata-limit-0.ll
llvm/test/CodeGen/RISCV/sdata-limit-4.ll
llvm/test/CodeGen/RISCV/sdata-limit-8.ll
llvm/test/CodeGen/RISCV/sdata-local-sym.ll
llvm/test/Transforms/LoopVectorize/RISCV/riscv-interleaved.ll

index 3258a97..57c9e58 100644 (file)
@@ -980,7 +980,7 @@ void CodeGenModule::EmitOpenCLMetadata() {
 void CodeGenModule::EmitBackendOptionsMetadata(
     const CodeGenOptions CodeGenOpts) {
   if (getTriple().isRISCV()) {
-    getModule().addModuleFlag(llvm::Module::Error, "SmallDataLimit",
+    getModule().addModuleFlag(llvm::Module::Min, "SmallDataLimit",
                               CodeGenOpts.SmallDataLimit);
   }
 }
index 89c9cc8..aa407c1 100644 (file)
 
 void test(void) {}
 
-// RV32-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8}
-// RV32-G4:      !{i32 1, !"SmallDataLimit", i32 4}
-// RV32-S0:      !{i32 1, !"SmallDataLimit", i32 0}
-// RV32-S2G4:    !{i32 1, !"SmallDataLimit", i32 4}
-// RV32-T16:     !{i32 1, !"SmallDataLimit", i32 16}
-// RV32-PIC:     !{i32 1, !"SmallDataLimit", i32 0}
+// RV32-DEFAULT: !{i32 8, !"SmallDataLimit", i32 8}
+// RV32-G4:      !{i32 8, !"SmallDataLimit", i32 4}
+// RV32-S0:      !{i32 8, !"SmallDataLimit", i32 0}
+// RV32-S2G4:    !{i32 8, !"SmallDataLimit", i32 4}
+// RV32-T16:     !{i32 8, !"SmallDataLimit", i32 16}
+// RV32-PIC:     !{i32 8, !"SmallDataLimit", i32 0}
 
-// RV64-DEFAULT: !{i32 1, !"SmallDataLimit", i32 8}
-// RV64-G4:      !{i32 1, !"SmallDataLimit", i32 4}
-// RV64-S0:      !{i32 1, !"SmallDataLimit", i32 0}
-// RV64-S2G4:    !{i32 1, !"SmallDataLimit", i32 4}
-// RV64-T16:     !{i32 1, !"SmallDataLimit", i32 16}
-// RV64-PIC:     !{i32 1, !"SmallDataLimit", i32 0}
-// RV64-LARGE:   !{i32 1, !"SmallDataLimit", i32 0}
+// RV64-DEFAULT: !{i32 8, !"SmallDataLimit", i32 8}
+// RV64-G4:      !{i32 8, !"SmallDataLimit", i32 4}
+// RV64-S0:      !{i32 8, !"SmallDataLimit", i32 0}
+// RV64-S2G4:    !{i32 8, !"SmallDataLimit", i32 4}
+// RV64-T16:     !{i32 8, !"SmallDataLimit", i32 16}
+// RV64-PIC:     !{i32 8, !"SmallDataLimit", i32 0}
+// RV64-LARGE:   !{i32 8, !"SmallDataLimit", i32 0}
 
 // The value will be passed by module flag instead of target feature.
 // RV32-S0-NOT: +small-data-limit=
index b65e657..9f4fca0 100644 (file)
@@ -29,11 +29,11 @@ unsigned long test_vlenb(void) {
 //.
 // RV32: !0 = !{i32 1, !"wchar_size", i32 4}
 // RV32: !1 = !{i32 1, !"target-abi", !"ilp32d"}
-// RV32: !2 = !{i32 1, !"SmallDataLimit", i32 0}
+// RV32: !2 = !{i32 8, !"SmallDataLimit", i32 0}
 // RV32: !3 = !{!"vlenb"}
 //.
 // RV64: !0 = !{i32 1, !"wchar_size", i32 4}
 // RV64: !1 = !{i32 1, !"target-abi", !"lp64d"}
-// RV64: !2 = !{i32 1, !"SmallDataLimit", i32 0}
+// RV64: !2 = !{i32 8, !"SmallDataLimit", i32 0}
 // RV64: !3 = !{!"vlenb"}
 //.
index 2c90cb9..5290802 100644 (file)
@@ -6,7 +6,7 @@
 
 ; SmallDataLimit set to 0, so we expect no data will put in sbss and sdata.
 !llvm.module.flags = !{!0}
-!0 = !{i32 1, !"SmallDataLimit", i32 0}
+!0 = !{i32 8, !"SmallDataLimit", i32 0}
 
 ; RV32-NOT:    .section        .sbss
 ; RV32-NOT:    .section        .sdata
index ec482cf..7e99a88 100644 (file)
@@ -7,7 +7,7 @@
 ; SmallDataLimit set to 4, so we expect @v will be put in sbss,
 ; but @r won't be put in sdata.
 !llvm.module.flags = !{!0}
-!0 = !{i32 1, !"SmallDataLimit", i32 4}
+!0 = !{i32 8, !"SmallDataLimit", i32 4}
 
 ; RV32:    .section        .sbss
 ; RV32-NOT:    .section        .sdata
index 1c67add..3efe773 100644 (file)
@@ -7,7 +7,7 @@
 ; SmallDataLimit set to 8, so we expect @v will be put in sbss
 ; and @r will be put in sdata.
 !llvm.module.flags = !{!0}
-!0 = !{i32 1, !"SmallDataLimit", i32 8}
+!0 = !{i32 8, !"SmallDataLimit", i32 8}
 
 ; RV32:    .section        .sbss
 ; RV32:    .section        .sdata
index b5032ae..e2336be 100644 (file)
@@ -8,7 +8,7 @@
 ; SmallDataLimit set to 8, so we expect @v will be put in sbss
 ; and @r will be put in sdata.
 !llvm.module.flags = !{!0}
-!0 = !{i32 1, !"SmallDataLimit", i32 8}
+!0 = !{i32 8, !"SmallDataLimit", i32 8}
 
 ; RV32:    .section        .sbss
 ; RV32:    .section        .sdata
index d51feae..5fc46c2 100644 (file)
@@ -41,7 +41,7 @@ attributes #0 = { nofree norecurse nosync nounwind writeonly "frame-pointer"="no
 
 !0 = !{i32 1, !"wchar_size", i32 4}
 !1 = !{i32 1, !"target-abi", !"lp64"}
-!2 = !{i32 1, !"SmallDataLimit", i32 8}
+!2 = !{i32 8, !"SmallDataLimit", i32 8}
 !3 = !{!"clang version 13.0.0"}
 !4 = !{!5, !5, i64 0}
 !5 = !{!"int", !6, i64 0}