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);
|
||||
}
|
||||
|
||||
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 *Inst,
|
||||
AtomicOrdering Ord) const {
|
||||
|
|
|
@ -93,6 +93,10 @@ public:
|
|||
getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI,
|
||||
StringRef Constraint, MVT VT) const override;
|
||||
|
||||
void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint,
|
||||
std::vector<SDValue> &Ops,
|
||||
SelectionDAG &DAG) const override;
|
||||
|
||||
MachineBasicBlock *
|
||||
EmitInstrWithCustomInserter(MachineInstr &MI,
|
||||
MachineBasicBlock *BB) const override;
|
||||
|
|
|
@ -82,4 +82,72 @@ define i32 @constraint_m2(i32* %a) nounwind {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue