forked from OSchip/llvm-project
[RISCV] Lower inline asm constraints I, J & K for RISC-V
This validates and lowers arguments to inline asm nodes which have the constraints I, J & K, with the following semantics (equivalent to GCC): I: Any 12-bit signed immediate. J: Immediate integer zero only. K: Any 5-bit unsigned immediate. Differential Revision: https://reviews.llvm.org/D54093 llvm-svn: 363054
This commit is contained in:
parent
f63feaf3c2
commit
28a5cadb3a
|
@ -2151,6 +2151,44 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||||
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
|
return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RISCVTargetLowering::LowerAsmOperandForConstraint(
|
||||||
|
SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops,
|
||||||
|
SelectionDAG &DAG) const {
|
||||||
|
// Currently only support length 1 constraints.
|
||||||
|
if (Constraint.length() == 1) {
|
||||||
|
switch (Constraint[0]) {
|
||||||
|
case 'I':
|
||||||
|
// Validate & create a 12-bit signed immediate operand.
|
||||||
|
if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
|
||||||
|
uint64_t CVal = C->getSExtValue();
|
||||||
|
if (isInt<12>(CVal))
|
||||||
|
Ops.push_back(
|
||||||
|
DAG.getTargetConstant(CVal, SDLoc(Op), Subtarget.getXLenVT()));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case 'J':
|
||||||
|
// Validate & create an integer zero operand.
|
||||||
|
if (auto *C = dyn_cast<ConstantSDNode>(Op))
|
||||||
|
if (C->getZExtValue() == 0)
|
||||||
|
Ops.push_back(
|
||||||
|
DAG.getTargetConstant(0, SDLoc(Op), Subtarget.getXLenVT()));
|
||||||
|
return;
|
||||||
|
case 'K':
|
||||||
|
// Validate & create a 5-bit unsigned immediate operand.
|
||||||
|
if (auto *C = dyn_cast<ConstantSDNode>(Op)) {
|
||||||
|
uint64_t CVal = C->getZExtValue();
|
||||||
|
if (isUInt<5>(CVal))
|
||||||
|
Ops.push_back(
|
||||||
|
DAG.getTargetConstant(CVal, SDLoc(Op), Subtarget.getXLenVT()));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG);
|
||||||
|
}
|
||||||
|
|
||||||
Instruction *RISCVTargetLowering::emitLeadingFence(IRBuilder<> &Builder,
|
Instruction *RISCVTargetLowering::emitLeadingFence(IRBuilder<> &Builder,
|
||||||
Instruction *Inst,
|
Instruction *Inst,
|
||||||
AtomicOrdering Ord) const {
|
AtomicOrdering Ord) const {
|
||||||
|
|
|
@ -93,6 +93,10 @@ public:
|
||||||
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||||
StringRef Constraint, MVT VT) const override;
|
StringRef Constraint, MVT VT) const override;
|
||||||
|
|
||||||
|
void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
|
||||||
|
std::vector<SDValue> &Ops,
|
||||||
|
SelectionDAG &DAG) const override;
|
||||||
|
|
||||||
MachineBasicBlock *
|
MachineBasicBlock *
|
||||||
EmitInstrWithCustomInserter(MachineInstr &MI,
|
EmitInstrWithCustomInserter(MachineInstr &MI,
|
||||||
MachineBasicBlock *BB) const override;
|
MachineBasicBlock *BB) const override;
|
||||||
|
|
|
@ -82,4 +82,72 @@ define i32 @constraint_m2(i32* %a) nounwind {
|
||||||
ret i32 %1
|
ret i32 %1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @constraint_I() {
|
||||||
|
; RV32I-LABEL: constraint_I:
|
||||||
|
; RV32I: # %bb.0:
|
||||||
|
; RV32I-NEXT: #APP
|
||||||
|
; RV32I-NEXT: addi a0, a0, 2047
|
||||||
|
; RV32I-NEXT: #NO_APP
|
||||||
|
; RV32I-NEXT: #APP
|
||||||
|
; RV32I-NEXT: addi a0, a0, -2048
|
||||||
|
; RV32I-NEXT: #NO_APP
|
||||||
|
; RV32I-NEXT: ret
|
||||||
|
;
|
||||||
|
; RV64I-LABEL: constraint_I:
|
||||||
|
; RV64I: # %bb.0:
|
||||||
|
; RV64I-NEXT: #APP
|
||||||
|
; RV64I-NEXT: addi a0, a0, 2047
|
||||||
|
; RV64I-NEXT: #NO_APP
|
||||||
|
; RV64I-NEXT: #APP
|
||||||
|
; RV64I-NEXT: addi a0, a0, -2048
|
||||||
|
; RV64I-NEXT: #NO_APP
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2047)
|
||||||
|
tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2048)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @constraint_J() {
|
||||||
|
; RV32I-LABEL: constraint_J:
|
||||||
|
; RV32I: # %bb.0:
|
||||||
|
; RV32I-NEXT: #APP
|
||||||
|
; RV32I-NEXT: addi a0, a0, 0
|
||||||
|
; RV32I-NEXT: #NO_APP
|
||||||
|
; RV32I-NEXT: ret
|
||||||
|
;
|
||||||
|
; RV64I-LABEL: constraint_J:
|
||||||
|
; RV64I: # %bb.0:
|
||||||
|
; RV64I-NEXT: #APP
|
||||||
|
; RV64I-NEXT: addi a0, a0, 0
|
||||||
|
; RV64I-NEXT: #NO_APP
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @constraint_K() {
|
||||||
|
; RV32I-LABEL: constraint_K:
|
||||||
|
; RV32I: # %bb.0:
|
||||||
|
; RV32I-NEXT: #APP
|
||||||
|
; RV32I-NEXT: csrwi mstatus, 31
|
||||||
|
; RV32I-NEXT: #NO_APP
|
||||||
|
; RV32I-NEXT: #APP
|
||||||
|
; RV32I-NEXT: csrwi mstatus, 0
|
||||||
|
; RV32I-NEXT: #NO_APP
|
||||||
|
; RV32I-NEXT: ret
|
||||||
|
;
|
||||||
|
; RV64I-LABEL: constraint_K:
|
||||||
|
; RV64I: # %bb.0:
|
||||||
|
; RV64I-NEXT: #APP
|
||||||
|
; RV64I-NEXT: csrwi mstatus, 31
|
||||||
|
; RV64I-NEXT: #NO_APP
|
||||||
|
; RV64I-NEXT: #APP
|
||||||
|
; RV64I-NEXT: csrwi mstatus, 0
|
||||||
|
; RV64I-NEXT: #NO_APP
|
||||||
|
; RV64I-NEXT: ret
|
||||||
|
tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 31)
|
||||||
|
tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 0)
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
; TODO: expend tests for more complex constraints, out of range immediates etc
|
; TODO: expend tests for more complex constraints, out of range immediates etc
|
||||||
|
|
Loading…
Reference in New Issue