diff --git a/llvm/lib/Target/SBF/SBFISelLowering.cpp b/llvm/lib/Target/SBF/SBFISelLowering.cpp index c7e429211a5718d..f3ca80513709abb 100644 --- a/llvm/lib/Target/SBF/SBFISelLowering.cpp +++ b/llvm/lib/Target/SBF/SBFISelLowering.cpp @@ -599,15 +599,10 @@ SDValue SBFTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, G->getOffset(), 0); } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); - } else if (ConstantSDNode * CNode = dyn_cast(Callee)) { - uint64_t Cte = CNode->getZExtValue(); - uint64_t U32Max = static_cast - (std::numeric_limits::max()); - if (Subtarget->getHasStaticSyscalls() && Cte >= U32Max - MaxSyscall) { - NodeCode = SBFISD::SYSCALL; - uint64_t SyscallCode = U32Max - Cte; - Callee = DAG.getConstant(SyscallCode, CLI.DL, MVT::i64); - } + } else if (isa(Callee) && Subtarget->getHasStaticSyscalls()) { + // When static syscalls are enabled and we have a constant operand for call, + // we emit a syscall. + NodeCode = SBFISD::SYSCALL; } // Returns a chain & a flag for retval copy to use. diff --git a/llvm/lib/Target/SBF/SBFInstrInfo.td b/llvm/lib/Target/SBF/SBFInstrInfo.td index 728ee17a53f678a..734fe58e13498f7 100644 --- a/llvm/lib/Target/SBF/SBFInstrInfo.td +++ b/llvm/lib/Target/SBF/SBFInstrInfo.td @@ -963,7 +963,7 @@ def : Pat<(i64 (and (i64 GPR:$src), 0xffffFFFF)), // Calls def : Pat<(SBFcall tglobaladdr:$dst), (JAL tglobaladdr:$dst)>; def : Pat<(SBFcall texternalsym:$dst), (JAL texternalsym:$dst)>; -def : Pat<(SBFcall imm:$dst), (JAL imm:$dst)>; +def : Pat<(SBFcall imm:$dst), (JAL imm:$dst)>, Requires<[SBFNoStaticSyscalls]>; def : Pat<(SBFcall GPR:$dst), (JALX GPR:$dst)>, Requires<[SBFNoCallxSrc]>; def : Pat<(SBFcall GPR:$dst), (JALX_v2 GPR:$dst)>, Requires<[SBFCallxSrc]>; def : Pat<(SBFSyscall imm:$imm), (SYSCALL_v3 imm:$imm)>, Requires<[SBFHasStaticSyscalls]>; diff --git a/llvm/test/CodeGen/SBF/call_internal.ll b/llvm/test/CodeGen/SBF/call_internal.ll index 8d92c6dc3063af0..8b181c5c07e776c 100644 --- a/llvm/test/CodeGen/SBF/call_internal.ll +++ b/llvm/test/CodeGen/SBF/call_internal.ll @@ -1,8 +1,8 @@ -; RUN: llc < %s -march=sbf --show-mc-encoding | FileCheck --check-prefix=CHECK-ASM %s -; RUN: llc -march=sbf --filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefix=CHECK-OBJ %s -; RUN: llc < %s -march=sbf -mcpu=sbfv2 --show-mc-encoding | FileCheck --check-prefix=CHECK-ASM %s +; RUN: llc < %s -march=sbf --show-mc-encoding | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-V0 %s +; RUN: llc -march=sbf --filetype=obj -o - %s | llvm-objdump -d - | FileCheck --check-prefixes=CHECK-OBJ,CHECK-OBJ-V0 %s +; RUN: llc < %s -march=sbf -mcpu=sbfv2 --show-mc-encoding | FileCheck --check-prefixes=CHECK-ASM,CHECK-ASM-V3 %s ; RUN: llc -march=sbf -mcpu=sbfv2 --filetype=obj -o - %s | llvm-objdump -d - -; | FileCheck --check-prefix=CHECK-OBJ %s +; | FileCheck --check-prefixes=CHECK-OBJ,CHECK-OBJ-V3 %s @.str = private unnamed_addr constant [5 x i8] c"foo\0A\00", align 1 @@ -16,8 +16,11 @@ entry: ; Function Attrs: nounwind define dso_local i64 @entrypoint(ptr noundef %input) local_unnamed_addr #1 { entry: -; CHECK-ASM: call 1811268606 # encoding: [0x85,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] -; CHECK-OBJ: 85 00 00 00 fe c3 f5 6b call 0x6bf5c3fe +; CHECK-ASM-V0: call 1811268606 # encoding: [0x85,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] +; CHECK-ASM-V3: syscall 1811268606 # encoding: [0x95,0x00,0x00,0x00,0xfe,0xc3,0xf5,0x6b] + +; CHECK-OBJ-V0: 85 00 00 00 fe c3 f5 6b call 0x6bf5c3fe +; CHECK-OBJ-V3: 95 00 00 00 fe c3 f5 6b syscall 0x6bf5c3fe tail call void inttoptr (i64 1811268606 to ptr)(ptr noundef nonnull @.str, i64 noundef 4) #3 %add.ptr = getelementptr inbounds i8, ptr %input, i64 4 diff --git a/llvm/test/CodeGen/SBF/static_syscall.ll b/llvm/test/CodeGen/SBF/static_syscall.ll index af1601ba5902147..fe5a66660e96a41 100644 --- a/llvm/test/CodeGen/SBF/static_syscall.ll +++ b/llvm/test/CodeGen/SBF/static_syscall.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=sbf < %s | FileCheck --check-prefix=CHECK-V1 %s -; RUN: llc -march=sbf -mattr=+static-syscalls -show-mc-encoding < %s | FileCheck --check-prefix=CHECK-V2 %s +; RUN: llc -march=sbf < %s | FileCheck --check-prefix=CHECK-V0 %s +; RUN: llc -march=sbf -mattr=+static-syscalls -show-mc-encoding < %s | FileCheck --check-prefix=CHECK-V3 %s ; Function Attrs: nounwind @@ -7,19 +7,19 @@ define dso_local i32 @test(i32 noundef %a, i32 noundef %b) { entry: ; CHECK-LABEL: test -; CHECK-V1: call -2 -; CHECK-V2: syscall 1 # encoding: [0x95,0x00,0x00,0x00,0x01,0x00,0x00,0x00] - %syscall_1 = tail call i32 inttoptr (i64 4294967294 to ptr)(i32 noundef %a, i32 noundef %b) +; CHECK-V0: call 2 +; CHECK-V3 syscall 2 # encoding: [0x95,0x00,0x00,0x00,0x01,0x00,0x00,0x00] + %syscall_1 = tail call i32 inttoptr (i64 2 to ptr)(i32 noundef %a, i32 noundef %b) -; CHECK-V1: call -12 -; CHECK-V2: syscall 11 # encoding: [0x95,0x00,0x00,0x00,0x0b,0x00,0x00,0x00] - %syscall_2 = tail call i32 inttoptr (i64 4294967284 to ptr)(i32 noundef %a, i32 noundef %b) +; CHECK-V0: call 11 +; CHECK-V3: syscall 11 # encoding: [0x95,0x00,0x00,0x00,0x0b,0x00,0x00,0x00] + %syscall_2 = tail call i32 inttoptr (i64 11 to ptr)(i32 noundef %a, i32 noundef %b) -; CHECK-V1: call -112 -; CHECK-V2: call -112 - %not_syscall = tail call i32 inttoptr (i64 4294967184 to ptr)(i32 noundef %a, i32 noundef %b) +; CHECK-V0: call 112 +; CHECK-V3: syscall 112 + %syscall_3 = tail call i32 inttoptr (i64 112 to ptr)(i32 noundef %a, i32 noundef %b) %add_1 = add i32 %syscall_1, %syscall_2 - %add_2 = add i32 %add_1, %not_syscall + %add_2 = add i32 %add_1, %syscall_3 ret i32 %add_1 } diff --git a/llvm/test/CodeGen/SBF/static_syscall_2.ll b/llvm/test/CodeGen/SBF/static_syscall_2.ll new file mode 100644 index 000000000000000..6c7ac56b5a873f5 --- /dev/null +++ b/llvm/test/CodeGen/SBF/static_syscall_2.ll @@ -0,0 +1,50 @@ +; RUN: llc -march=sbf -mattr=+static-syscalls < %s | FileCheck --check-prefix=CHECK %s + +; Syscall declaration in C: +; +; int c_declaration(int a, int b) { +; int (*const syscall)(int a, int b) = (void*)50; +; return syscall(a, b); +; } +; The following is the unoptimized output from clang: + +define dso_local i32 @c_declaration(i32 noundef %a, i32 noundef %b) #0 { +entry: + %a.addr = alloca i32, align 4 + %b.addr = alloca i32, align 4 + %syscall = alloca ptr, align 8 + store i32 %a, ptr %a.addr, align 4 + store i32 %b, ptr %b.addr, align 4 + store ptr inttoptr (i64 50 to ptr), ptr %syscall, align 8 + %0 = load i32, ptr %a.addr, align 4 + %1 = load i32, ptr %b.addr, align 4 + +; Ensure the syscall instruction is emitted +; CHECK: syscall 50 + + %call = call i32 inttoptr (i64 50 to ptr)(i32 noundef %0, i32 noundef %1) + ret i32 %call +} + +; Syscall declaration in Rust: +; +; #[no_mangle] +; pub unsafe fn rust_declaration(b: u64) -> u32 { +; let syscall : extern "C" fn(b: u64) -> u32 = core::mem::transmute(60u64); +; return syscall(b); +; } +; The following is the unoptimized output from rustc: + +define i32 @rust_declaration(i64 %b) unnamed_addr { +start: + %syscall.dbg.spill = alloca [8 x i8], align 8 + %b.dbg.spill = alloca [8 x i8], align 8 + store i64 %b, ptr %b.dbg.spill, align 8 + store ptr getelementptr (i8, ptr null, i64 60), ptr %syscall.dbg.spill, align 8 + +; Ensure the syscall instruction is emitted +; CHECK: syscall 60 + + %_0 = call i32 getelementptr (i8, ptr null, i64 60)(i64 %b) + ret i32 %_0 +} \ No newline at end of file