Skip to content

Commit

Permalink
[RISCV] Lower inline asm constraints I, J & K for RISC-V
Browse files Browse the repository at this point in the history
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



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363054 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
lewis-revill committed Jun 11, 2019
1 parent b6ddc4f commit e4d17eb
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
38 changes: 38 additions & 0 deletions lib/Target/RISCV/RISCVISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 4 additions & 0 deletions lib/Target/RISCV/RISCVISelLowering.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ class RISCVTargetLowering : public TargetLowering {
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;
Expand Down
68 changes: 68 additions & 0 deletions test/CodeGen/RISCV/inline-asm.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit e4d17eb

Please sign in to comment.