Skip to content

Commit

Permalink
[RISCV] Support inline assembly 'f' constraint for Zfinx.
Browse files Browse the repository at this point in the history
This would allow some inline assembly code work with either F or Zfinx.
This appears to match gcc behavior.

This will need to be adjust to exclude X0 after #112563.
  • Loading branch information
topperc committed Oct 18, 2024
1 parent 47d9ca8 commit ba60709
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 12 deletions.
48 changes: 36 additions & 12 deletions llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20392,12 +20392,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
return std::make_pair(0U, &RISCV::GPRPairRegClass);
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
case 'f':
if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16)
return std::make_pair(0U, &RISCV::FPR16RegClass);
if (Subtarget.hasStdExtF() && VT == MVT::f32)
return std::make_pair(0U, &RISCV::FPR32RegClass);
if (Subtarget.hasStdExtD() && VT == MVT::f64)
return std::make_pair(0U, &RISCV::FPR64RegClass);
if (VT == MVT::f16) {
if (Subtarget.hasStdExtZfhmin())
return std::make_pair(0U, &RISCV::FPR16RegClass);
if (Subtarget.hasStdExtZhinxmin())
return std::make_pair(0U, &RISCV::GPRF16RegClass);
} else if (VT == MVT::f32) {
if (Subtarget.hasStdExtF())
return std::make_pair(0U, &RISCV::FPR32RegClass);
if (Subtarget.hasStdExtZfinx())
return std::make_pair(0U, &RISCV::GPRF32RegClass);
} else if (VT == MVT::f64) {
if (Subtarget.hasStdExtD())
return std::make_pair(0U, &RISCV::FPR64RegClass);
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
return std::make_pair(0U, &RISCV::GPRPairRegClass);
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
return std::make_pair(0U, &RISCV::GPRNoX0RegClass);
}
break;
default:
break;
Expand Down Expand Up @@ -20440,12 +20452,24 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
if (!VT.isVector())
return std::make_pair(0U, &RISCV::GPRCRegClass);
} else if (Constraint == "cf") {
if (Subtarget.hasStdExtZfhmin() && VT == MVT::f16)
return std::make_pair(0U, &RISCV::FPR16CRegClass);
if (Subtarget.hasStdExtF() && VT == MVT::f32)
return std::make_pair(0U, &RISCV::FPR32CRegClass);
if (Subtarget.hasStdExtD() && VT == MVT::f64)
return std::make_pair(0U, &RISCV::FPR64CRegClass);
if (VT == MVT::f16) {
if (Subtarget.hasStdExtZfhmin())
return std::make_pair(0U, &RISCV::FPR16CRegClass);
if (Subtarget.hasStdExtZhinxmin())
return std::make_pair(0U, &RISCV::GPRF16CRegClass);
} else if (VT == MVT::f32) {
if (Subtarget.hasStdExtF())
return std::make_pair(0U, &RISCV::FPR32CRegClass);
if (Subtarget.hasStdExtZfinx())
return std::make_pair(0U, &RISCV::GPRF32CRegClass);
} else if (VT == MVT::f64) {
if (Subtarget.hasStdExtD())
return std::make_pair(0U, &RISCV::FPR64CRegClass);
if (Subtarget.hasStdExtZdinx() && !Subtarget.is64Bit())
return std::make_pair(0U, &RISCV::GPRPairCRegClass);
if (Subtarget.hasStdExtZdinx() && Subtarget.is64Bit())
return std::make_pair(0U, &RISCV::GPRCRegClass);
}
}

// Clang will correctly decode the usage of register name aliases into their
Expand Down
48 changes: 48 additions & 0 deletions llvm/test/CodeGen/RISCV/inline-asm-zdinx-constraint-r.ll
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,51 @@ define double @constraint_double_abi_name(double %a) nounwind {
%2 = tail call double asm "fadd.d $0, $1, $2", "={t1},{a0},{s0}"(double %a, double %1)
ret double %2
}

define double @constraint_f_double(double %a) nounwind {
; RV32FINX-LABEL: constraint_f_double:
; RV32FINX: # %bb.0:
; RV32FINX-NEXT: lui a2, %hi(gd)
; RV32FINX-NEXT: lw a3, %lo(gd+4)(a2)
; RV32FINX-NEXT: lw a2, %lo(gd)(a2)
; RV32FINX-NEXT: #APP
; RV32FINX-NEXT: fadd.d a0, a0, a2
; RV32FINX-NEXT: #NO_APP
; RV32FINX-NEXT: ret
;
; RV64FINX-LABEL: constraint_f_double:
; RV64FINX: # %bb.0:
; RV64FINX-NEXT: lui a1, %hi(gd)
; RV64FINX-NEXT: ld a1, %lo(gd)(a1)
; RV64FINX-NEXT: #APP
; RV64FINX-NEXT: fadd.d a0, a0, a1
; RV64FINX-NEXT: #NO_APP
; RV64FINX-NEXT: ret
%1 = load double, ptr @gd
%2 = tail call double asm "fadd.d $0, $1, $2", "=f,f,f"(double %a, double %1)
ret double %2
}

define double @constraint_cf_double(double %a) nounwind {
; RV32FINX-LABEL: constraint_cf_double:
; RV32FINX: # %bb.0:
; RV32FINX-NEXT: lui a2, %hi(gd)
; RV32FINX-NEXT: lw a3, %lo(gd+4)(a2)
; RV32FINX-NEXT: lw a2, %lo(gd)(a2)
; RV32FINX-NEXT: #APP
; RV32FINX-NEXT: fadd.d a0, a0, a2
; RV32FINX-NEXT: #NO_APP
; RV32FINX-NEXT: ret
;
; RV64FINX-LABEL: constraint_cf_double:
; RV64FINX: # %bb.0:
; RV64FINX-NEXT: lui a1, %hi(gd)
; RV64FINX-NEXT: ld a1, %lo(gd)(a1)
; RV64FINX-NEXT: #APP
; RV64FINX-NEXT: fadd.d a0, a0, a1
; RV64FINX-NEXT: #NO_APP
; RV64FINX-NEXT: ret
%1 = load double, ptr @gd
%2 = tail call double asm "fadd.d $0, $1, $2", "=^cf,^cf,^cf"(double %a, double %1)
ret double %2
}
45 changes: 45 additions & 0 deletions llvm/test/CodeGen/RISCV/inline-asm-zfinx-constraint-r.ll
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,48 @@ define float @constraint_float_abi_name(float %a) nounwind {
ret float %2
}

define float @constraint_f_float(float %a) nounwind {
; RV32FINX-LABEL: constraint_f_float:
; RV32FINX: # %bb.0:
; RV32FINX-NEXT: lui a1, %hi(gf)
; RV32FINX-NEXT: lw a1, %lo(gf)(a1)
; RV32FINX-NEXT: #APP
; RV32FINX-NEXT: fadd.s a0, a0, a1
; RV32FINX-NEXT: #NO_APP
; RV32FINX-NEXT: ret
;
; RV64FINX-LABEL: constraint_f_float:
; RV64FINX: # %bb.0:
; RV64FINX-NEXT: lui a1, %hi(gf)
; RV64FINX-NEXT: lw a1, %lo(gf)(a1)
; RV64FINX-NEXT: #APP
; RV64FINX-NEXT: fadd.s a0, a0, a1
; RV64FINX-NEXT: #NO_APP
; RV64FINX-NEXT: ret
%1 = load float, ptr @gf
%2 = tail call float asm "fadd.s $0, $1, $2", "=f,f,f"(float %a, float %1)
ret float %2
}

define float @constraint_cf_float(float %a) nounwind {
; RV32FINX-LABEL: constraint_cf_float:
; RV32FINX: # %bb.0:
; RV32FINX-NEXT: lui a1, %hi(gf)
; RV32FINX-NEXT: lw a1, %lo(gf)(a1)
; RV32FINX-NEXT: #APP
; RV32FINX-NEXT: fadd.s a0, a0, a1
; RV32FINX-NEXT: #NO_APP
; RV32FINX-NEXT: ret
;
; RV64FINX-LABEL: constraint_cf_float:
; RV64FINX: # %bb.0:
; RV64FINX-NEXT: lui a1, %hi(gf)
; RV64FINX-NEXT: lw a1, %lo(gf)(a1)
; RV64FINX-NEXT: #APP
; RV64FINX-NEXT: fadd.s a0, a0, a1
; RV64FINX-NEXT: #NO_APP
; RV64FINX-NEXT: ret
%1 = load float, ptr @gf
%2 = tail call float asm "fadd.s $0, $1, $2", "=^cf,cf,cf"(float %a, float %1)
ret float %2
}
82 changes: 82 additions & 0 deletions llvm/test/CodeGen/RISCV/inline-asm-zhinx-constraint-r.ll
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,85 @@ define half @constraint_half_abi_name(half %a) nounwind {
%2 = tail call half asm "fadd.s $0, $1, $2", "={t0},{a0},{s0}"(half %a, half %1)
ret half %2
}

define half @constraint_f_half(half %a) nounwind {
; RV32ZHINX-LABEL: constraint_f_half:
; RV32ZHINX: # %bb.0:
; RV32ZHINX-NEXT: lui a1, %hi(gh)
; RV32ZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV32ZHINX-NEXT: #APP
; RV32ZHINX-NEXT: fadd.h a0, a0, a1
; RV32ZHINX-NEXT: #NO_APP
; RV32ZHINX-NEXT: ret
;
; RV64ZHINX-LABEL: constraint_f_half:
; RV64ZHINX: # %bb.0:
; RV64ZHINX-NEXT: lui a1, %hi(gh)
; RV64ZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV64ZHINX-NEXT: #APP
; RV64ZHINX-NEXT: fadd.h a0, a0, a1
; RV64ZHINX-NEXT: #NO_APP
; RV64ZHINX-NEXT: ret
;
; RV32DINXZHINX-LABEL: constraint_f_half:
; RV32DINXZHINX: # %bb.0:
; RV32DINXZHINX-NEXT: lui a1, %hi(gh)
; RV32DINXZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV32DINXZHINX-NEXT: #APP
; RV32DINXZHINX-NEXT: fadd.h a0, a0, a1
; RV32DINXZHINX-NEXT: #NO_APP
; RV32DINXZHINX-NEXT: ret
;
; RV64DINXZHINX-LABEL: constraint_f_half:
; RV64DINXZHINX: # %bb.0:
; RV64DINXZHINX-NEXT: lui a1, %hi(gh)
; RV64DINXZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV64DINXZHINX-NEXT: #APP
; RV64DINXZHINX-NEXT: fadd.h a0, a0, a1
; RV64DINXZHINX-NEXT: #NO_APP
; RV64DINXZHINX-NEXT: ret
%1 = load half, ptr @gh
%2 = tail call half asm "fadd.h $0, $1, $2", "=f,f,f"(half %a, half %1)
ret half %2
}

define half @constraint_cf_half(half %a) nounwind {
; RV32ZHINX-LABEL: constraint_cf_half:
; RV32ZHINX: # %bb.0:
; RV32ZHINX-NEXT: lui a1, %hi(gh)
; RV32ZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV32ZHINX-NEXT: #APP
; RV32ZHINX-NEXT: fadd.h a0, a0, a1
; RV32ZHINX-NEXT: #NO_APP
; RV32ZHINX-NEXT: ret
;
; RV64ZHINX-LABEL: constraint_cf_half:
; RV64ZHINX: # %bb.0:
; RV64ZHINX-NEXT: lui a1, %hi(gh)
; RV64ZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV64ZHINX-NEXT: #APP
; RV64ZHINX-NEXT: fadd.h a0, a0, a1
; RV64ZHINX-NEXT: #NO_APP
; RV64ZHINX-NEXT: ret
;
; RV32DINXZHINX-LABEL: constraint_cf_half:
; RV32DINXZHINX: # %bb.0:
; RV32DINXZHINX-NEXT: lui a1, %hi(gh)
; RV32DINXZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV32DINXZHINX-NEXT: #APP
; RV32DINXZHINX-NEXT: fadd.h a0, a0, a1
; RV32DINXZHINX-NEXT: #NO_APP
; RV32DINXZHINX-NEXT: ret
;
; RV64DINXZHINX-LABEL: constraint_cf_half:
; RV64DINXZHINX: # %bb.0:
; RV64DINXZHINX-NEXT: lui a1, %hi(gh)
; RV64DINXZHINX-NEXT: lh a1, %lo(gh)(a1)
; RV64DINXZHINX-NEXT: #APP
; RV64DINXZHINX-NEXT: fadd.h a0, a0, a1
; RV64DINXZHINX-NEXT: #NO_APP
; RV64DINXZHINX-NEXT: ret
%1 = load half, ptr @gh
%2 = tail call half asm "fadd.h $0, $1, $2", "=^cf,^cf,^cf"(half %a, half %1)
ret half %2
}

0 comments on commit ba60709

Please sign in to comment.