Skip to content

Commit

Permalink
Re-commit of r238201 with fix for building with shared libraries.
Browse files Browse the repository at this point in the history
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@238739 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
Luke Cheeseman committed Jun 1, 2015
1 parent af0e519 commit 7d97fc4
Show file tree
Hide file tree
Showing 16 changed files with 983 additions and 22 deletions.
127 changes: 127 additions & 0 deletions lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ class AArch64DAGToDAGISel : public SelectionDAGISel {

SDNode *SelectLIBM(SDNode *N);

SDNode *SelectReadRegister(SDNode *N);
SDNode *SelectWriteRegister(SDNode *N);

// Include the pieces autogenerated from the target description.
#include "AArch64GenDAGISel.inc"

Expand Down Expand Up @@ -2114,6 +2117,120 @@ AArch64DAGToDAGISel::SelectCVTFixedPosOperand(SDValue N, SDValue &FixedPos,
return true;
}

// Inspects a register string of the form o0:op1:CRn:CRm:op2 gets the fields
// of the string and obtains the integer values from them and combines these
// into a single value to be used in the MRS/MSR instruction.
static int getIntOperandFromRegisterString(StringRef RegString) {
SmallVector<StringRef, 5> Fields;
RegString.split(Fields, ":");

if (Fields.size() == 1)
return -1;

assert(Fields.size() == 5
&& "Invalid number of fields in read register string");

SmallVector<int, 5> Ops;
bool AllIntFields = true;

for (StringRef Field : Fields) {
unsigned IntField;
AllIntFields &= !Field.getAsInteger(10, IntField);
Ops.push_back(IntField);
}

assert(AllIntFields &&
"Unexpected non-integer value in special register string.");

// Need to combine the integer fields of the string into a single value
// based on the bit encoding of MRS/MSR instruction.
return (Ops[0] << 14) | (Ops[1] << 11) | (Ops[2] << 7) |
(Ops[3] << 3) | (Ops[4]);
}

// Lower the read_register intrinsic to an MRS instruction node if the special
// register string argument is either of the form detailed in the ALCE (the
// form described in getIntOperandsFromRegsterString) or is a named register
// known by the MRS SysReg mapper.
SDNode *AArch64DAGToDAGISel::SelectReadRegister(SDNode *N) {
const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
SDLoc DL(N);

int Reg = getIntOperandFromRegisterString(RegString->getString());
if (Reg != -1)
return CurDAG->getMachineNode(AArch64::MRS, DL, N->getSimpleValueType(0),
MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
N->getOperand(0));

// Use the sysreg mapper to map the remaining possible strings to the
// value for the register to be used for the instruction operand.
AArch64SysReg::MRSMapper mapper;
bool IsValidSpecialReg;
Reg = mapper.fromString(RegString->getString(),
Subtarget->getFeatureBits(),
IsValidSpecialReg);
if (IsValidSpecialReg)
return CurDAG->getMachineNode(AArch64::MRS, DL, N->getSimpleValueType(0),
MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
N->getOperand(0));

return nullptr;
}

// Lower the write_register intrinsic to an MSR instruction node if the special
// register string argument is either of the form detailed in the ALCE (the
// form described in getIntOperandsFromRegsterString) or is a named register
// known by the MSR SysReg mapper.
SDNode *AArch64DAGToDAGISel::SelectWriteRegister(SDNode *N) {
const MDNodeSDNode *MD = dyn_cast<MDNodeSDNode>(N->getOperand(1));
const MDString *RegString = dyn_cast<MDString>(MD->getMD()->getOperand(0));
SDLoc DL(N);

int Reg = getIntOperandFromRegisterString(RegString->getString());
if (Reg != -1)
return CurDAG->getMachineNode(AArch64::MSR, DL, MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
N->getOperand(2), N->getOperand(0));

// Check if the register was one of those allowed as the pstatefield value in
// the MSR (immediate) instruction. To accept the values allowed in the
// pstatefield for the MSR (immediate) instruction, we also require that an
// immediate value has been provided as an argument, we know that this is
// the case as it has been ensured by semantic checking.
AArch64PState::PStateMapper PMapper;
bool IsValidSpecialReg;
Reg = PMapper.fromString(RegString->getString(),
Subtarget->getFeatureBits(),
IsValidSpecialReg);
if (IsValidSpecialReg) {
assert (isa<ConstantSDNode>(N->getOperand(2))
&& "Expected a constant integer expression.");
uint64_t Immed = cast<ConstantSDNode>(N->getOperand(2))->getZExtValue();
return CurDAG->getMachineNode(AArch64::MSRpstate, DL, MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
CurDAG->getTargetConstant(Immed, DL, MVT::i16),
N->getOperand(0));
}

// Use the sysreg mapper to attempt to map the remaining possible strings
// to the value for the register to be used for the MSR (register)
// instruction operand.
AArch64SysReg::MSRMapper Mapper;
Reg = Mapper.fromString(RegString->getString(),
Subtarget->getFeatureBits(),
IsValidSpecialReg);

if (IsValidSpecialReg)
return CurDAG->getMachineNode(AArch64::MSR, DL, MVT::Other,
CurDAG->getTargetConstant(Reg, DL, MVT::i32),
N->getOperand(2), N->getOperand(0));

return nullptr;
}

SDNode *AArch64DAGToDAGISel::Select(SDNode *Node) {
// Dump information about the Node being selected
DEBUG(errs() << "Selecting: ");
Expand All @@ -2135,6 +2252,16 @@ SDNode *AArch64DAGToDAGISel::Select(SDNode *Node) {
default:
break;

case ISD::READ_REGISTER:
if (SDNode *Res = SelectReadRegister(Node))
return Res;
break;

case ISD::WRITE_REGISTER:
if (SDNode *Res = SelectWriteRegister(Node))
return Res;
break;

case ISD::ADD:
if (SDNode *I = SelectMLAV64LaneV128(Node))
return I;
Expand Down
3 changes: 2 additions & 1 deletion lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4065,7 +4065,8 @@ unsigned AArch64TargetLowering::getRegisterByName(const char* RegName,
.Default(0);
if (Reg)
return Reg;
report_fatal_error("Invalid register name global variable");
report_fatal_error(Twine("Invalid register name \""
+ StringRef(RegName) + "\"."));
}

SDValue AArch64TargetLowering::LowerRETURNADDR(SDValue Op,
Expand Down
2 changes: 1 addition & 1 deletion lib/Target/AArch64/LLVMBuild.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ has_jit = 1
type = Library
name = AArch64CodeGen
parent = AArch64
required_libraries = AArch64AsmPrinter AArch64Desc AArch64Info Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target
required_libraries = AArch64AsmPrinter AArch64Desc AArch64Info AArch64Utils Analysis AsmPrinter CodeGen Core MC Scalar SelectionDAG Support Target
add_to_library_groups = AArch64
Loading

0 comments on commit 7d97fc4

Please sign in to comment.