From 3d89fb4d13bc3af1c3643a310b90fce51a649119 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Tue, 13 Jul 2021 09:30:09 -0700 Subject: [PATCH] [RISCV] Support machine constraint "S" Similar to D46745, "S" represents an absolute symbolic operand, which can be used to specify the access models, e.g. extern int var; void *addr_via_asm() { void *ret; asm("lui %0, %%hi(%1)\naddi %0,%0,%%lo(%1)" : "=r"(ret) : "S"(&var)); return ret; } 'S' is documented in trunk GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101275 Reviewed By: luismarques Differential Revision: https://reviews.llvm.org/D105254 --- clang/lib/Basic/Targets/RISCV.cpp | 3 ++ clang/test/CodeGen/RISCV/riscv-inline-asm.c | 6 +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 11 +++++ llvm/test/CodeGen/RISCV/inline-asm-S-constraint.ll | 54 ++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/inline-asm-S-constraint.ll diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 1f31f47..9705129 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -87,6 +87,9 @@ bool RISCVTargetInfo::validateAsmConstraint( // An address that is held in a general-purpose register. Info.setAllowsMemory(); return true; + case 'S': // A symbolic address + Info.setAllowsRegister(); + return true; case 'v': // A vector register. if (Name[1] == 'r' || Name[1] == 'm') { diff --git a/clang/test/CodeGen/RISCV/riscv-inline-asm.c b/clang/test/CodeGen/RISCV/riscv-inline-asm.c index dea900f..2303293 100644 --- a/clang/test/CodeGen/RISCV/riscv-inline-asm.c +++ b/clang/test/CodeGen/RISCV/riscv-inline-asm.c @@ -44,3 +44,9 @@ void test_A(int *p) { // CHECK: call void asm sideeffect "", "*A"(i32* %p) asm volatile("" :: "A"(*p)); } + +void test_S() { +// CHECK-LABEL: define{{.*}} void @test_S() +// CHECK: call void asm sideeffect "", "S"(float* nonnull @f) + asm volatile("" :: "S"(&f)); +} diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ab0d018..a81aec1 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -8294,6 +8294,8 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const { return C_Immediate; case 'A': return C_Memory; + case 'S': // A symbolic address + return C_Other; } } return TargetLowering::getConstraintType(Constraint); @@ -8523,6 +8525,15 @@ void RISCVTargetLowering::LowerAsmOperandForConstraint( DAG.getTargetConstant(CVal, SDLoc(Op), Subtarget.getXLenVT())); } return; + case 'S': + if (const auto *GA = dyn_cast(Op)) { + Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(Op), + GA->getValueType(0))); + } else if (const auto *BA = dyn_cast(Op)) { + Ops.push_back(DAG.getTargetBlockAddress(BA->getBlockAddress(), + BA->getValueType(0))); + } + return; default: break; } diff --git a/llvm/test/CodeGen/RISCV/inline-asm-S-constraint.ll b/llvm/test/CodeGen/RISCV/inline-asm-S-constraint.ll new file mode 100644 index 0000000..2387978 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-S-constraint.ll @@ -0,0 +1,54 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 < %s | FileCheck %s --check-prefix=RV32 +; RUN: llc -mtriple=riscv64 < %s | FileCheck %s --check-prefix=RV64 + +@var = external dso_local global i32, align 4 + +define dso_local i8* @constraint_S() { +; RV32-LABEL: constraint_S: +; RV32: # %bb.0: +; RV32-NEXT: #APP +; RV32-NEXT: lui a0, %hi(var) +; RV32-NEXT: addi a0, a0, %lo(var) +; RV32-NEXT: #NO_APP +; RV32-NEXT: ret +; +; RV64-LABEL: constraint_S: +; RV64: # %bb.0: +; RV64-NEXT: #APP +; RV64-NEXT: lui a0, %hi(var) +; RV64-NEXT: addi a0, a0, %lo(var) +; RV64-NEXT: #NO_APP +; RV64-NEXT: ret + %ret = tail call i8* asm "lui $0, %hi($1)\0Aaddi $0, $0, %lo($1)", "=r,S"(i32* nonnull @var) + ret i8* %ret +} + +; Function Attrs: nofree nosync nounwind readnone +define dso_local i8* @constraint_S_label() { +; RV32-LABEL: constraint_S_label: +; RV32: # %bb.0: # %entry +; RV32-NEXT: .Ltmp0: # Block address taken +; RV32-NEXT: # %bb.1: # %L1 +; RV32-NEXT: #APP +; RV32-NEXT: lui a0, %hi(.Ltmp0) +; RV32-NEXT: addi a0, a0, %lo(.Ltmp0) +; RV32-NEXT: #NO_APP +; RV32-NEXT: ret +; +; RV64-LABEL: constraint_S_label: +; RV64: # %bb.0: # %entry +; RV64-NEXT: .Ltmp0: # Block address taken +; RV64-NEXT: # %bb.1: # %L1 +; RV64-NEXT: #APP +; RV64-NEXT: lui a0, %hi(.Ltmp0) +; RV64-NEXT: addi a0, a0, %lo(.Ltmp0) +; RV64-NEXT: #NO_APP +; RV64-NEXT: ret +entry: + br label %L1 + +L1: + %ret = tail call i8* asm "lui $0, %hi($1)\0Aaddi $0, $0, %lo($1)", "=r,S"(i8* blockaddress(@constraint_S_label, %L1)) + ret i8* %ret +} -- 2.7.4