mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
Hexagon V5 (floating point) support.
llvm-svn: 155367
This commit is contained in:
parent
4bcbe40295
commit
9f4844f7da
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,8 @@ def ArchV3 : SubtargetFeature<"v3", "HexagonArchVersion", "V3",
|
|||||||
"Hexagon v3">;
|
"Hexagon v3">;
|
||||||
def ArchV4 : SubtargetFeature<"v4", "HexagonArchVersion", "V4",
|
def ArchV4 : SubtargetFeature<"v4", "HexagonArchVersion", "V4",
|
||||||
"Hexagon v4">;
|
"Hexagon v4">;
|
||||||
|
def ArchV5 : SubtargetFeature<"v5", "HexagonArchVersion", "V5",
|
||||||
|
"Hexagon v5">;
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Register File, Calling Conv, Instruction Descriptions
|
// Register File, Calling Conv, Instruction Descriptions
|
||||||
@ -52,6 +54,8 @@ class Proc<string Name, ProcessorItineraries Itin,
|
|||||||
def : Proc<"hexagonv2", HexagonItineraries, [ArchV2]>;
|
def : Proc<"hexagonv2", HexagonItineraries, [ArchV2]>;
|
||||||
def : Proc<"hexagonv3", HexagonItineraries, [ArchV2, ArchV3]>;
|
def : Proc<"hexagonv3", HexagonItineraries, [ArchV2, ArchV3]>;
|
||||||
def : Proc<"hexagonv4", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4]>;
|
def : Proc<"hexagonv4", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4]>;
|
||||||
|
def : Proc<"hexagonv5", HexagonItinerariesV4, [ArchV2, ArchV3, ArchV4, ArchV5]>;
|
||||||
|
|
||||||
|
|
||||||
// Hexagon Uses the MC printer for assembler output, so make sure the TableGen
|
// Hexagon Uses the MC printer for assembler output, so make sure the TableGen
|
||||||
// AsmWriter bits get associated with the correct class.
|
// AsmWriter bits get associated with the correct class.
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
|
|
||||||
// Hexagon 32-bit C return-value convention.
|
// Hexagon 32-bit C return-value convention.
|
||||||
def RetCC_Hexagon32 : CallingConv<[
|
def RetCC_Hexagon32 : CallingConv<[
|
||||||
CCIfType<[i32], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
CCIfType<[i32, f32], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
||||||
CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>,
|
CCIfType<[i64, f64], CCAssignToReg<[D0, D1, D2]>>,
|
||||||
|
|
||||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||||
CCAssignToStack<4, 4>
|
CCAssignToStack<4, 4>
|
||||||
@ -27,8 +27,8 @@ def RetCC_Hexagon32 : CallingConv<[
|
|||||||
// Hexagon 32-bit C Calling convention.
|
// Hexagon 32-bit C Calling convention.
|
||||||
def CC_Hexagon32 : CallingConv<[
|
def CC_Hexagon32 : CallingConv<[
|
||||||
// All arguments get passed in integer registers if there is space.
|
// All arguments get passed in integer registers if there is space.
|
||||||
CCIfType<[i32, i16, i8], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
CCIfType<[f32, i32, i16, i8], CCAssignToReg<[R0, R1, R2, R3, R4, R5]>>,
|
||||||
CCIfType<[i64], CCAssignToReg<[D0, D1, D2]>>,
|
CCIfType<[f64, i64], CCAssignToReg<[D0, D1, D2]>>,
|
||||||
|
|
||||||
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
// Alternatively, they are assigned to the stack in 4-byte aligned units.
|
||||||
CCAssignToStack<4, 4>
|
CCAssignToStack<4, 4>
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
//
|
//
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// The Hexagon processor has no instructions that load or store predicate
|
// The Hexagon processor has no instructions that load or store predicate
|
||||||
// registers directly. So, when these registers must be spilled a general
|
// registers directly. So, when these registers must be spilled a general
|
||||||
// purpose register must be found and the value copied to/from it from/to
|
// purpose register must be found and the value copied to/from it from/to
|
||||||
// the predicate register. This code currently does not use the register
|
// the predicate register. This code currently does not use the register
|
||||||
// scavenger mechanism available in the allocator. There are two registers
|
// scavenger mechanism available in the allocator. There are two registers
|
||||||
// reserved to allow spilling/restoring predicate registers. One is used to
|
// reserved to allow spilling/restoring predicate registers. One is used to
|
||||||
// hold the predicate value. The other is used when stack frame offsets are
|
// hold the predicate value. The other is used when stack frame offsets are
|
||||||
@ -84,7 +84,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
int SrcReg = MI->getOperand(2).getReg();
|
int SrcReg = MI->getOperand(2).getReg();
|
||||||
assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
|
assert(Hexagon::PredRegsRegClass.contains(SrcReg) &&
|
||||||
"Not a predicate register");
|
"Not a predicate register");
|
||||||
if (!TII->isValidOffset(Hexagon::STriw, Offset)) {
|
if (!TII->isValidOffset(Hexagon::STriw_indexed, Offset)) {
|
||||||
if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) {
|
if (!TII->isValidOffset(Hexagon::ADD_ri, Offset)) {
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
TII->get(Hexagon::CONST32_Int_Real),
|
TII->get(Hexagon::CONST32_Int_Real),
|
||||||
@ -95,7 +95,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
TII->get(Hexagon::STriw))
|
TII->get(Hexagon::STriw_indexed))
|
||||||
.addReg(HEXAGON_RESERVED_REG_1)
|
.addReg(HEXAGON_RESERVED_REG_1)
|
||||||
.addImm(0).addReg(HEXAGON_RESERVED_REG_2);
|
.addImm(0).addReg(HEXAGON_RESERVED_REG_2);
|
||||||
} else {
|
} else {
|
||||||
@ -103,7 +103,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
|
HEXAGON_RESERVED_REG_1).addReg(FP).addImm(Offset);
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw))
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw_indexed))
|
||||||
.addReg(HEXAGON_RESERVED_REG_1)
|
.addReg(HEXAGON_RESERVED_REG_1)
|
||||||
.addImm(0)
|
.addImm(0)
|
||||||
.addReg(HEXAGON_RESERVED_REG_2);
|
.addReg(HEXAGON_RESERVED_REG_2);
|
||||||
@ -111,7 +111,7 @@ bool HexagonExpandPredSpillCode::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
} else {
|
} else {
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_RsPd),
|
||||||
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
HEXAGON_RESERVED_REG_2).addReg(SrcReg);
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw)).
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::STriw_indexed)).
|
||||||
addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
|
addReg(FP).addImm(Offset).addReg(HEXAGON_RESERVED_REG_2);
|
||||||
}
|
}
|
||||||
MII = MBB->erase(MI);
|
MII = MBB->erase(MI);
|
||||||
|
@ -90,7 +90,9 @@ public:
|
|||||||
SDNode *SelectMul(SDNode *N);
|
SDNode *SelectMul(SDNode *N);
|
||||||
SDNode *SelectZeroExtend(SDNode *N);
|
SDNode *SelectZeroExtend(SDNode *N);
|
||||||
SDNode *SelectIntrinsicWOChain(SDNode *N);
|
SDNode *SelectIntrinsicWOChain(SDNode *N);
|
||||||
|
SDNode *SelectIntrinsicWChain(SDNode *N);
|
||||||
SDNode *SelectConstant(SDNode *N);
|
SDNode *SelectConstant(SDNode *N);
|
||||||
|
SDNode *SelectConstantFP(SDNode *N);
|
||||||
SDNode *SelectAdd(SDNode *N);
|
SDNode *SelectAdd(SDNode *N);
|
||||||
|
|
||||||
// Include the pieces autogenerated from the target description.
|
// Include the pieces autogenerated from the target description.
|
||||||
@ -318,6 +320,8 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetLoad(LoadSDNode *LD, DebugLoc dl) {
|
|||||||
else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
|
else if (LoadedVT == MVT::i32) Opcode = Hexagon::LDriw_indexed;
|
||||||
else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
|
else if (LoadedVT == MVT::i16) Opcode = Hexagon::LDrih_indexed;
|
||||||
else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
|
else if (LoadedVT == MVT::i8) Opcode = Hexagon::LDrib_indexed;
|
||||||
|
else if (LoadedVT == MVT::f32) Opcode = Hexagon::LDriw_indexed_f;
|
||||||
|
else if (LoadedVT == MVT::f64) Opcode = Hexagon::LDrid_indexed_f;
|
||||||
else assert (0 && "unknown memory type");
|
else assert (0 && "unknown memory type");
|
||||||
|
|
||||||
// Build indexed load.
|
// Build indexed load.
|
||||||
@ -375,7 +379,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
|
|||||||
};
|
};
|
||||||
ReplaceUses(Froms, Tos, 3);
|
ReplaceUses(Froms, Tos, 3);
|
||||||
return Result_2;
|
return Result_2;
|
||||||
}
|
}
|
||||||
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
|
SDValue TargetConst0 = CurDAG->getTargetConstant(0, MVT::i32);
|
||||||
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
|
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, MVT::i32);
|
||||||
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
|
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
|
||||||
@ -636,7 +640,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, DebugLoc dl) {
|
|||||||
|
|
||||||
// Figure out the opcode.
|
// Figure out the opcode.
|
||||||
if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
|
if (StoredVT == MVT::i64) Opcode = Hexagon::STrid;
|
||||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw;
|
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
|
||||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
|
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih;
|
||||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
|
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib;
|
||||||
else assert (0 && "unknown memory type");
|
else assert (0 && "unknown memory type");
|
||||||
@ -693,6 +697,8 @@ SDNode *HexagonDAGToDAGISel::SelectBaseOffsetStore(StoreSDNode *ST,
|
|||||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
|
else if (StoredVT == MVT::i32) Opcode = Hexagon::STriw_indexed;
|
||||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
|
else if (StoredVT == MVT::i16) Opcode = Hexagon::STrih_indexed;
|
||||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
|
else if (StoredVT == MVT::i8) Opcode = Hexagon::STrib_indexed;
|
||||||
|
else if (StoredVT == MVT::f32) Opcode = Hexagon::STriw_indexed_f;
|
||||||
|
else if (StoredVT == MVT::f64) Opcode = Hexagon::STrid_indexed_f;
|
||||||
else assert (0 && "unknown memory type");
|
else assert (0 && "unknown memory type");
|
||||||
|
|
||||||
SDValue Ops[] = {SDValue(NewBase,0),
|
SDValue Ops[] = {SDValue(NewBase,0),
|
||||||
@ -723,7 +729,7 @@ SDNode *HexagonDAGToDAGISel::SelectStore(SDNode *N) {
|
|||||||
if (AM != ISD::UNINDEXED) {
|
if (AM != ISD::UNINDEXED) {
|
||||||
return SelectIndexedStore(ST, dl);
|
return SelectIndexedStore(ST, dl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SelectBaseOffsetStore(ST, dl);
|
return SelectBaseOffsetStore(ST, dl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +758,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
|
|||||||
if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
|
if (MulOp0.getOpcode() == ISD::SIGN_EXTEND) {
|
||||||
SDValue Sext0 = MulOp0.getOperand(0);
|
SDValue Sext0 = MulOp0.getOperand(0);
|
||||||
if (Sext0.getNode()->getValueType(0) != MVT::i32) {
|
if (Sext0.getNode()->getValueType(0) != MVT::i32) {
|
||||||
SelectCode(N);
|
return SelectCode(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
OP0 = Sext0;
|
OP0 = Sext0;
|
||||||
@ -761,7 +767,7 @@ SDNode *HexagonDAGToDAGISel::SelectMul(SDNode *N) {
|
|||||||
if (LD->getMemoryVT() != MVT::i32 ||
|
if (LD->getMemoryVT() != MVT::i32 ||
|
||||||
LD->getExtensionType() != ISD::SEXTLOAD ||
|
LD->getExtensionType() != ISD::SEXTLOAD ||
|
||||||
LD->getAddressingMode() != ISD::UNINDEXED) {
|
LD->getAddressingMode() != ISD::UNINDEXED) {
|
||||||
SelectCode(N);
|
return SelectCode(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue Chain = LD->getChain();
|
SDValue Chain = LD->getChain();
|
||||||
@ -1158,6 +1164,25 @@ SDNode *HexagonDAGToDAGISel::SelectIntrinsicWOChain(SDNode *N) {
|
|||||||
return SelectCode(N);
|
return SelectCode(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Map floating point constant values.
|
||||||
|
//
|
||||||
|
SDNode *HexagonDAGToDAGISel::SelectConstantFP(SDNode *N) {
|
||||||
|
DebugLoc dl = N->getDebugLoc();
|
||||||
|
ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(N);
|
||||||
|
APFloat APF = CN->getValueAPF();
|
||||||
|
if (N->getValueType(0) == MVT::f32) {
|
||||||
|
return CurDAG->getMachineNode(Hexagon::TFRI_f, dl, MVT::f32,
|
||||||
|
CurDAG->getTargetConstantFP(APF.convertToFloat(), MVT::f32));
|
||||||
|
}
|
||||||
|
else if (N->getValueType(0) == MVT::f64) {
|
||||||
|
return CurDAG->getMachineNode(Hexagon::CONST64_Float_Real, dl, MVT::f64,
|
||||||
|
CurDAG->getTargetConstantFP(APF.convertToDouble(), MVT::f64));
|
||||||
|
}
|
||||||
|
|
||||||
|
return SelectCode(N);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Map predicate true (encoded as -1 in LLVM) to a XOR.
|
// Map predicate true (encoded as -1 in LLVM) to a XOR.
|
||||||
@ -1234,6 +1259,9 @@ SDNode *HexagonDAGToDAGISel::Select(SDNode *N) {
|
|||||||
case ISD::Constant:
|
case ISD::Constant:
|
||||||
return SelectConstant(N);
|
return SelectConstant(N);
|
||||||
|
|
||||||
|
case ISD::ConstantFP:
|
||||||
|
return SelectConstantFP(N);
|
||||||
|
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
return SelectAdd(N);
|
return SelectAdd(N);
|
||||||
|
|
||||||
|
@ -103,12 +103,12 @@ CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
|
|||||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (LocVT == MVT::i32) {
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
||||||
ofst = State.AllocateStack(4, 4);
|
ofst = State.AllocateStack(4, 4);
|
||||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (LocVT == MVT::i64) {
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
||||||
ofst = State.AllocateStack(8, 8);
|
ofst = State.AllocateStack(8, 8);
|
||||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||||
return false;
|
return false;
|
||||||
@ -142,12 +142,12 @@ CC_Hexagon (unsigned ValNo, MVT ValVT,
|
|||||||
LocInfo = CCValAssign::AExt;
|
LocInfo = CCValAssign::AExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocVT == MVT::i32) {
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
||||||
if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocVT == MVT::i64) {
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
||||||
if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -217,12 +217,12 @@ static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
|
|||||||
LocInfo = CCValAssign::AExt;
|
LocInfo = CCValAssign::AExt;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocVT == MVT::i32) {
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
||||||
if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LocVT == MVT::i64) {
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
||||||
if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -234,7 +234,7 @@ static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|||||||
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||||
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
||||||
|
|
||||||
if (LocVT == MVT::i32) {
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
||||||
if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
|
if (unsigned Reg = State.AllocateReg(Hexagon::R0)) {
|
||||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
||||||
return false;
|
return false;
|
||||||
@ -249,7 +249,7 @@ static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|||||||
static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
|
static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
|
||||||
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||||
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
||||||
if (LocVT == MVT::i64) {
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
||||||
if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
|
if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
|
||||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
||||||
return false;
|
return false;
|
||||||
@ -839,7 +839,8 @@ const {
|
|||||||
// 1. int, long long, ptr args that get allocated in register.
|
// 1. int, long long, ptr args that get allocated in register.
|
||||||
// 2. Large struct that gets an register to put its address in.
|
// 2. Large struct that gets an register to put its address in.
|
||||||
EVT RegVT = VA.getLocVT();
|
EVT RegVT = VA.getLocVT();
|
||||||
if (RegVT == MVT::i8 || RegVT == MVT::i16 || RegVT == MVT::i32) {
|
if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
|
||||||
|
RegVT == MVT::i32 || RegVT == MVT::f32) {
|
||||||
unsigned VReg =
|
unsigned VReg =
|
||||||
RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
|
RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
|
||||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||||
@ -918,14 +919,33 @@ HexagonTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
|
|
||||||
SDValue
|
SDValue
|
||||||
HexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
|
HexagonTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const {
|
||||||
|
SDValue LHS = Op.getOperand(0);
|
||||||
|
SDValue RHS = Op.getOperand(1);
|
||||||
|
SDValue CC = Op.getOperand(4);
|
||||||
|
SDValue TrueVal = Op.getOperand(2);
|
||||||
|
SDValue FalseVal = Op.getOperand(3);
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
SDNode* OpNode = Op.getNode();
|
SDNode* OpNode = Op.getNode();
|
||||||
|
EVT SVT = OpNode->getValueType(0);
|
||||||
|
|
||||||
SDValue Cond = DAG.getNode(ISD::SETCC, Op.getDebugLoc(), MVT::i1,
|
SDValue Cond = DAG.getNode(ISD::SETCC, dl, MVT::i1, LHS, RHS, CC);
|
||||||
Op.getOperand(2), Op.getOperand(3),
|
return DAG.getNode(ISD::SELECT, dl, SVT, Cond, TrueVal, FalseVal);
|
||||||
Op.getOperand(4));
|
}
|
||||||
return DAG.getNode(ISD::SELECT, Op.getDebugLoc(), OpNode->getValueType(0),
|
|
||||||
Cond, Op.getOperand(0),
|
SDValue
|
||||||
Op.getOperand(1));
|
HexagonTargetLowering::LowerConstantPool(SDValue Op, SelectionDAG &DAG) const {
|
||||||
|
EVT ValTy = Op.getValueType();
|
||||||
|
|
||||||
|
DebugLoc dl = Op.getDebugLoc();
|
||||||
|
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
|
||||||
|
SDValue Res;
|
||||||
|
if (CP->isMachineConstantPoolEntry())
|
||||||
|
Res = DAG.getTargetConstantPool(CP->getMachineCPVal(), ValTy,
|
||||||
|
CP->getAlignment());
|
||||||
|
else
|
||||||
|
Res = DAG.getTargetConstantPool(CP->getConstVal(), ValTy,
|
||||||
|
CP->getAlignment());
|
||||||
|
return DAG.getNode(HexagonISD::CONST32, dl, ValTy, Res);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue
|
SDValue
|
||||||
@ -1010,10 +1030,17 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
|
|||||||
: TargetLowering(targetmachine, new HexagonTargetObjectFile()),
|
: TargetLowering(targetmachine, new HexagonTargetObjectFile()),
|
||||||
TM(targetmachine) {
|
TM(targetmachine) {
|
||||||
|
|
||||||
|
const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
|
||||||
|
|
||||||
// Set up the register classes.
|
// Set up the register classes.
|
||||||
addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
|
addRegisterClass(MVT::i32, &Hexagon::IntRegsRegClass);
|
||||||
addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
|
addRegisterClass(MVT::i64, &Hexagon::DoubleRegsRegClass);
|
||||||
|
|
||||||
|
if (QRI->Subtarget.hasV5TOps()) {
|
||||||
|
addRegisterClass(MVT::f32, &Hexagon::IntRegsRegClass);
|
||||||
|
addRegisterClass(MVT::f64, &Hexagon::DoubleRegsRegClass);
|
||||||
|
}
|
||||||
|
|
||||||
addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
|
addRegisterClass(MVT::i1, &Hexagon::PredRegsRegClass);
|
||||||
|
|
||||||
computeRegisterProperties();
|
computeRegisterProperties();
|
||||||
@ -1028,32 +1055,16 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
|
|||||||
//
|
//
|
||||||
// Library calls for unsupported operations
|
// Library calls for unsupported operations
|
||||||
//
|
//
|
||||||
setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
|
|
||||||
setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
|
setLibcallName(RTLIB::SINTTOFP_I128_F64, "__hexagon_floattidf");
|
||||||
setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
|
setLibcallName(RTLIB::SINTTOFP_I128_F32, "__hexagon_floattisf");
|
||||||
setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
|
|
||||||
setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
|
|
||||||
setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
|
|
||||||
setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
|
setLibcallName(RTLIB::FPTOUINT_F32_I128, "__hexagon_fixunssfti");
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
|
|
||||||
setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
|
setLibcallName(RTLIB::FPTOUINT_F64_I128, "__hexagon_fixunsdfti");
|
||||||
|
|
||||||
setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
|
|
||||||
setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
|
|
||||||
setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
|
setLibcallName(RTLIB::FPTOSINT_F32_I128, "__hexagon_fixsfti");
|
||||||
setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
|
|
||||||
setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
|
setLibcallName(RTLIB::FPTOSINT_F64_I128, "__hexagon_fixdfti");
|
||||||
|
|
||||||
setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
|
setLibcallName(RTLIB::SDIV_I32, "__hexagon_divsi3");
|
||||||
setOperationAction(ISD::SDIV, MVT::i32, Expand);
|
setOperationAction(ISD::SDIV, MVT::i32, Expand);
|
||||||
setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3");
|
setLibcallName(RTLIB::SREM_I32, "__hexagon_umodsi3");
|
||||||
@ -1082,93 +1093,185 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
|
|||||||
setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
|
setLibcallName(RTLIB::DIV_F64, "__hexagon_divdf3");
|
||||||
setOperationAction(ISD::FDIV, MVT::f64, Expand);
|
setOperationAction(ISD::FDIV, MVT::f64, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2");
|
setOperationAction(ISD::FSQRT, MVT::f32, Expand);
|
||||||
setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand);
|
setOperationAction(ISD::FSQRT, MVT::f64, Expand);
|
||||||
|
setOperationAction(ISD::FSIN, MVT::f32, Expand);
|
||||||
|
setOperationAction(ISD::FSIN, MVT::f64, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
|
if (QRI->Subtarget.hasV5TOps()) {
|
||||||
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
|
// Hexagon V5 Support.
|
||||||
|
setOperationAction(ISD::FADD, MVT::f32, Legal);
|
||||||
|
setOperationAction(ISD::FADD, MVT::f64, Legal);
|
||||||
|
setOperationAction(ISD::FP_EXTEND, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETOEQ, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETOEQ, MVT::f64, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUEQ, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUEQ, MVT::f64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
|
setCondCodeAction(ISD::SETOGE, MVT::f32, Legal);
|
||||||
setOperationAction(ISD::FADD, MVT::f64, Expand);
|
setCondCodeAction(ISD::SETOGE, MVT::f64, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUGE, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUGE, MVT::f64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
|
setCondCodeAction(ISD::SETOGT, MVT::f32, Legal);
|
||||||
setOperationAction(ISD::FADD, MVT::f32, Expand);
|
setCondCodeAction(ISD::SETOGT, MVT::f64, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUGT, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETUGT, MVT::f64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
|
setCondCodeAction(ISD::SETOLE, MVT::f32, Legal);
|
||||||
setOperationAction(ISD::FADD, MVT::f32, Expand);
|
setCondCodeAction(ISD::SETOLE, MVT::f64, Legal);
|
||||||
|
setCondCodeAction(ISD::SETOLT, MVT::f32, Legal);
|
||||||
|
setCondCodeAction(ISD::SETOLT, MVT::f64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
|
setOperationAction(ISD::ConstantFP, MVT::f32, Legal);
|
||||||
setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
|
setOperationAction(ISD::ConstantFP, MVT::f64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
|
setOperationAction(ISD::FP_TO_UINT, MVT::i1, Promote);
|
||||||
setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i1, Promote);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i1, Promote);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i1, Promote);
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
|
setOperationAction(ISD::FP_TO_UINT, MVT::i8, Promote);
|
||||||
setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i8, Promote);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i8, Promote);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i8, Promote);
|
||||||
|
|
||||||
setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
|
setOperationAction(ISD::FP_TO_UINT, MVT::i16, Promote);
|
||||||
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i16, Promote);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i16, Promote);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
|
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Legal);
|
||||||
setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Legal);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Legal);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
|
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Legal);
|
||||||
setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Legal);
|
||||||
|
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Legal);
|
||||||
|
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Legal);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
|
setOperationAction(ISD::FABS, MVT::f32, Legal);
|
||||||
setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
|
setOperationAction(ISD::FABS, MVT::f64, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
|
setOperationAction(ISD::FNEG, MVT::f32, Legal);
|
||||||
setCondCodeAction(ISD::SETOLE, MVT::f64, Expand);
|
setOperationAction(ISD::FNEG, MVT::f64, Expand);
|
||||||
|
} else {
|
||||||
|
|
||||||
setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
|
// Expand fp<->uint.
|
||||||
setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
|
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Expand);
|
||||||
|
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
|
setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand);
|
||||||
setCondCodeAction(ISD::SETOLT, MVT::f64, Expand);
|
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
|
setLibcallName(RTLIB::SINTTOFP_I64_F32, "__hexagon_floatdisf");
|
||||||
setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
|
setLibcallName(RTLIB::UINTTOFP_I64_F32, "__hexagon_floatundisf");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I32_F32, "__hexagon_floatunsisf");
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I32_F32, "__hexagon_floatsisf");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I64_F64, "__hexagon_floatdidf");
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I64_F64, "__hexagon_floatundidf");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UINTTOFP_I32_F64, "__hexagon_floatunsidf");
|
||||||
|
setLibcallName(RTLIB::SINTTOFP_I32_F64, "__hexagon_floatsidf");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F32_I32, "__hexagon_fixunssfsi");
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F32_I64, "__hexagon_fixunssfdi");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F64_I64, "__hexagon_fixdfdi");
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F32_I64, "__hexagon_fixsfdi");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F64_I32, "__hexagon_fixunsdfsi");
|
||||||
|
setLibcallName(RTLIB::FPTOUINT_F64_I64, "__hexagon_fixunsdfdi");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::ADD_F64, "__hexagon_adddf3");
|
||||||
|
setOperationAction(ISD::FADD, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::ADD_F32, "__hexagon_addsf3");
|
||||||
|
setOperationAction(ISD::FADD, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPEXT_F32_F64, "__hexagon_extendsfdf2");
|
||||||
|
setOperationAction(ISD::FP_EXTEND, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OEQ_F32, "__hexagon_eqsf2");
|
||||||
|
setCondCodeAction(ISD::SETOEQ, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
|
||||||
|
setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OGE_F32, "__hexagon_gesf2");
|
||||||
|
setCondCodeAction(ISD::SETOGE, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OGE_F64, "__hexagon_gedf2");
|
||||||
|
setCondCodeAction(ISD::SETOGE, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OGT_F32, "__hexagon_gtsf2");
|
||||||
|
setCondCodeAction(ISD::SETOGT, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OGT_F64, "__hexagon_gtdf2");
|
||||||
|
setCondCodeAction(ISD::SETOGT, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F64_I32, "__hexagon_fixdfsi");
|
||||||
|
setOperationAction(ISD::FP_TO_SINT, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPTOSINT_F32_I32, "__hexagon_fixsfsi");
|
||||||
|
setOperationAction(ISD::FP_TO_SINT, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OLE_F64, "__hexagon_ledf2");
|
||||||
|
setCondCodeAction(ISD::SETOLE, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OLE_F32, "__hexagon_lesf2");
|
||||||
|
setCondCodeAction(ISD::SETOLE, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OLT_F64, "__hexagon_ltdf2");
|
||||||
|
setCondCodeAction(ISD::SETOLT, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::OLT_F32, "__hexagon_ltsf2");
|
||||||
|
setCondCodeAction(ISD::SETOLT, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
|
||||||
|
setOperationAction(ISD::FMUL, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
|
||||||
|
setOperationAction(ISD::MUL, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
|
||||||
|
setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
|
||||||
|
setOperationAction(ISD::SUB, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
|
||||||
|
setOperationAction(ISD::SUB, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2");
|
||||||
|
setOperationAction(ISD::FP_ROUND, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2");
|
||||||
|
setCondCodeAction(ISD::SETUO, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2");
|
||||||
|
setCondCodeAction(ISD::SETO, MVT::f64, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2");
|
||||||
|
setCondCodeAction(ISD::SETO, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2");
|
||||||
|
setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
|
||||||
|
|
||||||
|
setOperationAction(ISD::FABS, MVT::f32, Expand);
|
||||||
|
setOperationAction(ISD::FABS, MVT::f64, Expand);
|
||||||
|
setOperationAction(ISD::FNEG, MVT::f32, Expand);
|
||||||
|
setOperationAction(ISD::FNEG, MVT::f64, Expand);
|
||||||
|
}
|
||||||
|
|
||||||
setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
|
setLibcallName(RTLIB::SREM_I32, "__hexagon_modsi3");
|
||||||
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
setOperationAction(ISD::SREM, MVT::i32, Expand);
|
||||||
|
|
||||||
setLibcallName(RTLIB::MUL_F64, "__hexagon_muldf3");
|
|
||||||
setOperationAction(ISD::FMUL, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::MUL_F32, "__hexagon_mulsf3");
|
|
||||||
setOperationAction(ISD::MUL, MVT::f32, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::UNE_F64, "__hexagon_nedf2");
|
|
||||||
setCondCodeAction(ISD::SETUNE, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::UNE_F32, "__hexagon_nesf2");
|
|
||||||
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::SUB_F64, "__hexagon_subdf3");
|
|
||||||
setOperationAction(ISD::SUB, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::SUB_F32, "__hexagon_subsf3");
|
|
||||||
setOperationAction(ISD::SUB, MVT::f32, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::FPROUND_F64_F32, "__hexagon_truncdfsf2");
|
|
||||||
setOperationAction(ISD::FP_ROUND, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::UO_F64, "__hexagon_unorddf2");
|
|
||||||
setCondCodeAction(ISD::SETUO, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::O_F64, "__hexagon_unorddf2");
|
|
||||||
setCondCodeAction(ISD::SETO, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::OEQ_F64, "__hexagon_eqdf2");
|
|
||||||
setCondCodeAction(ISD::SETOEQ, MVT::f64, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::O_F32, "__hexagon_unordsf2");
|
|
||||||
setCondCodeAction(ISD::SETO, MVT::f32, Expand);
|
|
||||||
|
|
||||||
setLibcallName(RTLIB::UO_F32, "__hexagon_unordsf2");
|
|
||||||
setCondCodeAction(ISD::SETUO, MVT::f32, Expand);
|
|
||||||
|
|
||||||
setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
|
setIndexedLoadAction(ISD::POST_INC, MVT::i8, Legal);
|
||||||
setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
|
setIndexedLoadAction(ISD::POST_INC, MVT::i16, Legal);
|
||||||
setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
|
setIndexedLoadAction(ISD::POST_INC, MVT::i32, Legal);
|
||||||
@ -1208,20 +1311,33 @@ HexagonTargetLowering::HexagonTargetLowering(HexagonTargetMachine
|
|||||||
|
|
||||||
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
|
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
|
||||||
|
|
||||||
// Expand fp<->uint.
|
|
||||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
|
|
||||||
setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand);
|
|
||||||
|
|
||||||
// Hexagon has no select or setcc: expand to SELECT_CC.
|
|
||||||
setOperationAction(ISD::SELECT, MVT::f32, Expand);
|
|
||||||
setOperationAction(ISD::SELECT, MVT::f64, Expand);
|
|
||||||
|
|
||||||
// Lower SELECT_CC to SETCC and SELECT.
|
// Lower SELECT_CC to SETCC and SELECT.
|
||||||
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
|
setOperationAction(ISD::SELECT_CC, MVT::i32, Custom);
|
||||||
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
setOperationAction(ISD::SELECT_CC, MVT::i64, Custom);
|
||||||
// This is a workaround documented in DAGCombiner.cpp:2892 We don't
|
|
||||||
// support SELECT_CC on every type.
|
if (QRI->Subtarget.hasV5TOps()) {
|
||||||
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
|
||||||
|
// We need to make the operation type of SELECT node to be Custom,
|
||||||
|
// such that we don't go into the infinite loop of
|
||||||
|
// select -> setcc -> select_cc -> select loop.
|
||||||
|
setOperationAction(ISD::SELECT, MVT::f32, Custom);
|
||||||
|
setOperationAction(ISD::SELECT, MVT::f64, Custom);
|
||||||
|
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::f32, Expand);
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::f64, Expand);
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Hexagon has no select or setcc: expand to SELECT_CC.
|
||||||
|
setOperationAction(ISD::SELECT, MVT::f32, Expand);
|
||||||
|
setOperationAction(ISD::SELECT, MVT::f64, Expand);
|
||||||
|
|
||||||
|
// This is a workaround documented in DAGCombiner.cpp:2892 We don't
|
||||||
|
// support SELECT_CC on every type.
|
||||||
|
setOperationAction(ISD::SELECT_CC, MVT::Other, Expand);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
setOperationAction(ISD::BR_CC, MVT::Other, Expand);
|
||||||
setOperationAction(ISD::BRIND, MVT::Other, Expand);
|
setOperationAction(ISD::BRIND, MVT::Other, Expand);
|
||||||
@ -1307,22 +1423,22 @@ const char*
|
|||||||
HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
HexagonTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
switch (Opcode) {
|
switch (Opcode) {
|
||||||
default: return 0;
|
default: return 0;
|
||||||
case HexagonISD::CONST32: return "HexagonISD::CONST32";
|
case HexagonISD::CONST32: return "HexagonISD::CONST32";
|
||||||
case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
|
case HexagonISD::ADJDYNALLOC: return "HexagonISD::ADJDYNALLOC";
|
||||||
case HexagonISD::CMPICC: return "HexagonISD::CMPICC";
|
case HexagonISD::CMPICC: return "HexagonISD::CMPICC";
|
||||||
case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC";
|
case HexagonISD::CMPFCC: return "HexagonISD::CMPFCC";
|
||||||
case HexagonISD::BRICC: return "HexagonISD::BRICC";
|
case HexagonISD::BRICC: return "HexagonISD::BRICC";
|
||||||
case HexagonISD::BRFCC: return "HexagonISD::BRFCC";
|
case HexagonISD::BRFCC: return "HexagonISD::BRFCC";
|
||||||
case HexagonISD::SELECT_ICC: return "HexagonISD::SELECT_ICC";
|
case HexagonISD::SELECT_ICC: return "HexagonISD::SELECT_ICC";
|
||||||
case HexagonISD::SELECT_FCC: return "HexagonISD::SELECT_FCC";
|
case HexagonISD::SELECT_FCC: return "HexagonISD::SELECT_FCC";
|
||||||
case HexagonISD::Hi: return "HexagonISD::Hi";
|
case HexagonISD::Hi: return "HexagonISD::Hi";
|
||||||
case HexagonISD::Lo: return "HexagonISD::Lo";
|
case HexagonISD::Lo: return "HexagonISD::Lo";
|
||||||
case HexagonISD::FTOI: return "HexagonISD::FTOI";
|
case HexagonISD::FTOI: return "HexagonISD::FTOI";
|
||||||
case HexagonISD::ITOF: return "HexagonISD::ITOF";
|
case HexagonISD::ITOF: return "HexagonISD::ITOF";
|
||||||
case HexagonISD::CALL: return "HexagonISD::CALL";
|
case HexagonISD::CALL: return "HexagonISD::CALL";
|
||||||
case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG";
|
case HexagonISD::RET_FLAG: return "HexagonISD::RET_FLAG";
|
||||||
case HexagonISD::BR_JT: return "HexagonISD::BR_JT";
|
case HexagonISD::BR_JT: return "HexagonISD::BR_JT";
|
||||||
case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN";
|
case HexagonISD::TC_RETURN: return "HexagonISD::TC_RETURN";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1347,9 +1463,10 @@ SDValue
|
|||||||
HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
||||||
switch (Op.getOpcode()) {
|
switch (Op.getOpcode()) {
|
||||||
default: llvm_unreachable("Should not custom lower this!");
|
default: llvm_unreachable("Should not custom lower this!");
|
||||||
|
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||||
// Frame & Return address. Currently unimplemented.
|
// Frame & Return address. Currently unimplemented.
|
||||||
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
|
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
|
||||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||||
case ISD::GlobalTLSAddress:
|
case ISD::GlobalTLSAddress:
|
||||||
llvm_unreachable("TLS not implemented for Hexagon.");
|
llvm_unreachable("TLS not implemented for Hexagon.");
|
||||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
|
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG);
|
||||||
@ -1359,9 +1476,10 @@ HexagonTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
|
|||||||
case ISD::BR_JT: return LowerBR_JT(Op, DAG);
|
case ISD::BR_JT: return LowerBR_JT(Op, DAG);
|
||||||
|
|
||||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||||
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||||
|
case ISD::SELECT: return Op;
|
||||||
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||||
case ISD::INLINEASM: return LowerINLINEASM(Op, DAG);
|
case ISD::INLINEASM: return LowerINLINEASM(Op, DAG);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1404,8 +1522,10 @@ HexagonTargetLowering::getRegForInlineAsmConstraint(const
|
|||||||
case MVT::i32:
|
case MVT::i32:
|
||||||
case MVT::i16:
|
case MVT::i16:
|
||||||
case MVT::i8:
|
case MVT::i8:
|
||||||
|
case MVT::f32:
|
||||||
return std::make_pair(0U, &Hexagon::IntRegsRegClass);
|
return std::make_pair(0U, &Hexagon::IntRegsRegClass);
|
||||||
case MVT::i64:
|
case MVT::i64:
|
||||||
|
case MVT::f64:
|
||||||
return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
|
return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -1416,6 +1536,14 @@ HexagonTargetLowering::getRegForInlineAsmConstraint(const
|
|||||||
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
|
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isFPImmLegal - Returns true if the target can instruction select the
|
||||||
|
/// specified FP immediate natively. If false, the legalizer will
|
||||||
|
/// materialize the FP immediate as a load from a constant pool.
|
||||||
|
bool HexagonTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const {
|
||||||
|
const HexagonRegisterInfo* QRI = TM.getRegisterInfo();
|
||||||
|
return QRI->Subtarget.hasV5TOps();
|
||||||
|
}
|
||||||
|
|
||||||
/// isLegalAddressingMode - Return true if the addressing mode represented by
|
/// isLegalAddressingMode - Return true if the addressing mode represented by
|
||||||
/// AM is legal for this target, for a load/store of the specified type.
|
/// AM is legal for this target, for a load/store of the specified type.
|
||||||
bool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
bool HexagonTargetLowering::isLegalAddressingMode(const AddrMode &AM,
|
||||||
|
@ -27,6 +27,7 @@ namespace llvm {
|
|||||||
|
|
||||||
CONST32,
|
CONST32,
|
||||||
CONST32_GP, // For marking data present in GP.
|
CONST32_GP, // For marking data present in GP.
|
||||||
|
FCONST32,
|
||||||
SETCC,
|
SETCC,
|
||||||
ADJDYNALLOC,
|
ADJDYNALLOC,
|
||||||
ARGEXTEND,
|
ARGEXTEND,
|
||||||
@ -48,6 +49,7 @@ namespace llvm {
|
|||||||
BR_JT, // Jump table.
|
BR_JT, // Jump table.
|
||||||
BARRIER, // Memory barrier.
|
BARRIER, // Memory barrier.
|
||||||
WrapperJT,
|
WrapperJT,
|
||||||
|
WrapperCP,
|
||||||
TC_RETURN
|
TC_RETURN
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -128,6 +130,7 @@ namespace llvm {
|
|||||||
MachineBasicBlock *BB) const;
|
MachineBasicBlock *BB) const;
|
||||||
|
|
||||||
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
|
||||||
|
SDValue LowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
|
||||||
virtual EVT getSetCCResultType(EVT VT) const {
|
virtual EVT getSetCCResultType(EVT VT) const {
|
||||||
return MVT::i1;
|
return MVT::i1;
|
||||||
}
|
}
|
||||||
@ -150,6 +153,7 @@ namespace llvm {
|
|||||||
/// mode is legal for a load/store of any legal type.
|
/// mode is legal for a load/store of any legal type.
|
||||||
/// TODO: Handle pre/postinc as well.
|
/// TODO: Handle pre/postinc as well.
|
||||||
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
|
virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
|
||||||
|
virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
|
||||||
|
|
||||||
/// isLegalICmpImmediate - Return true if the specified immediate is legal
|
/// isLegalICmpImmediate - Return true if the specified immediate is legal
|
||||||
/// icmp immediate, that is the target has icmp instructions which can
|
/// icmp immediate, that is the target has icmp instructions which can
|
||||||
|
@ -178,7 +178,7 @@ class MInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
|||||||
// Definition of the instruction class NOT CHANGED.
|
// Definition of the instruction class NOT CHANGED.
|
||||||
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
// Name of the Instruction Class changed from M to XTYPE from V2/V3 to V4.
|
||||||
class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
class MInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||||
string cstr>
|
string cstr>
|
||||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, M, TypeXTYPE> {
|
: InstHexagon<outs, ins, asmstr, pattern, cstr, M, TypeXTYPE> {
|
||||||
bits<5> rd;
|
bits<5> rd;
|
||||||
bits<5> rs;
|
bits<5> rs;
|
||||||
@ -201,7 +201,7 @@ class SInst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
|||||||
// Definition of the instruction class NOT CHANGED.
|
// Definition of the instruction class NOT CHANGED.
|
||||||
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
// Name of the Instruction Class changed from S to XTYPE from V2/V3 to V4.
|
||||||
class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
class SInst_acc<dag outs, dag ins, string asmstr, list<dag> pattern,
|
||||||
string cstr>
|
string cstr>
|
||||||
: InstHexagon<outs, ins, asmstr, pattern, cstr, S, TypeXTYPE> {
|
: InstHexagon<outs, ins, asmstr, pattern, cstr, S, TypeXTYPE> {
|
||||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
// : InstHexagon<outs, ins, asmstr, pattern, cstr, S> {
|
||||||
// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> {
|
// : InstHexagon<outs, ins, asmstr, pattern, cstr, !if(V4T, XTYPE_V4, S)> {
|
||||||
|
@ -716,6 +716,12 @@ bool HexagonInstrInfo::isExtended(const MachineInstr *MI) const {
|
|||||||
|
|
||||||
// TFR_FI
|
// TFR_FI
|
||||||
case Hexagon::TFR_FI_immext_V4:
|
case Hexagon::TFR_FI_immext_V4:
|
||||||
|
|
||||||
|
// TFRI_F
|
||||||
|
case Hexagon::TFRI_f:
|
||||||
|
case Hexagon::TFRI_cPt_f:
|
||||||
|
case Hexagon::TFRI_cNotPt_f:
|
||||||
|
case Hexagon::CONST64_Float_Real:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1893,6 +1899,9 @@ getMatchingCondBranchOpcode(int Opc, bool invertPredicate) const {
|
|||||||
case Hexagon::TFR:
|
case Hexagon::TFR:
|
||||||
return !invertPredicate ? Hexagon::TFR_cPt :
|
return !invertPredicate ? Hexagon::TFR_cPt :
|
||||||
Hexagon::TFR_cNotPt;
|
Hexagon::TFR_cNotPt;
|
||||||
|
case Hexagon::TFRI_f:
|
||||||
|
return !invertPredicate ? Hexagon::TFRI_cPt_f :
|
||||||
|
Hexagon::TFRI_cNotPt_f;
|
||||||
case Hexagon::TFRI:
|
case Hexagon::TFRI:
|
||||||
return !invertPredicate ? Hexagon::TFRI_cPt :
|
return !invertPredicate ? Hexagon::TFRI_cPt :
|
||||||
Hexagon::TFRI_cNotPt;
|
Hexagon::TFRI_cNotPt;
|
||||||
@ -2337,13 +2346,17 @@ isValidOffset(const int Opcode, const int Offset) const {
|
|||||||
switch(Opcode) {
|
switch(Opcode) {
|
||||||
|
|
||||||
case Hexagon::LDriw:
|
case Hexagon::LDriw:
|
||||||
|
case Hexagon::LDriw_f:
|
||||||
case Hexagon::STriw:
|
case Hexagon::STriw:
|
||||||
|
case Hexagon::STriw_f:
|
||||||
assert((Offset % 4 == 0) && "Offset has incorrect alignment");
|
assert((Offset % 4 == 0) && "Offset has incorrect alignment");
|
||||||
return (Offset >= Hexagon_MEMW_OFFSET_MIN) &&
|
return (Offset >= Hexagon_MEMW_OFFSET_MIN) &&
|
||||||
(Offset <= Hexagon_MEMW_OFFSET_MAX);
|
(Offset <= Hexagon_MEMW_OFFSET_MAX);
|
||||||
|
|
||||||
case Hexagon::LDrid:
|
case Hexagon::LDrid:
|
||||||
|
case Hexagon::LDrid_f:
|
||||||
case Hexagon::STrid:
|
case Hexagon::STrid:
|
||||||
|
case Hexagon::STrid_f:
|
||||||
assert((Offset % 8 == 0) && "Offset has incorrect alignment");
|
assert((Offset % 8 == 0) && "Offset has incorrect alignment");
|
||||||
return (Offset >= Hexagon_MEMD_OFFSET_MIN) &&
|
return (Offset >= Hexagon_MEMD_OFFSET_MIN) &&
|
||||||
(Offset <= Hexagon_MEMD_OFFSET_MAX);
|
(Offset <= Hexagon_MEMD_OFFSET_MAX);
|
||||||
|
@ -107,6 +107,8 @@ public:
|
|||||||
|
|
||||||
unsigned createVR(MachineFunction* MF, MVT VT) const;
|
unsigned createVR(MachineFunction* MF, MVT VT) const;
|
||||||
|
|
||||||
|
virtual bool isExtendable(const MachineInstr* MI) const;
|
||||||
|
virtual bool isExtended(const MachineInstr* MI) const;
|
||||||
virtual bool isPredicable(MachineInstr *MI) const;
|
virtual bool isPredicable(MachineInstr *MI) const;
|
||||||
virtual bool
|
virtual bool
|
||||||
PredicateInstruction(MachineInstr *MI,
|
PredicateInstruction(MachineInstr *MI,
|
||||||
@ -136,6 +138,10 @@ public:
|
|||||||
isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumCycles,
|
isProfitableToDupForIfCvt(MachineBasicBlock &MBB,unsigned NumCycles,
|
||||||
const BranchProbability &Probability) const;
|
const BranchProbability &Probability) const;
|
||||||
|
|
||||||
|
unsigned getInvertedPredicatedOpcode(const int Opcode) const;
|
||||||
|
unsigned getImmExtForm(const MachineInstr* MI) const;
|
||||||
|
unsigned getNormalBranchForm(const MachineInstr* MI) const;
|
||||||
|
|
||||||
virtual DFAPacketizer*
|
virtual DFAPacketizer*
|
||||||
CreateTargetScheduleState(const TargetMachine *TM,
|
CreateTargetScheduleState(const TargetMachine *TM,
|
||||||
const ScheduleDAG *DAG) const;
|
const ScheduleDAG *DAG) const;
|
||||||
@ -160,21 +166,16 @@ public:
|
|||||||
bool isS8_Immediate(const int value) const;
|
bool isS8_Immediate(const int value) const;
|
||||||
bool isS6_Immediate(const int value) const;
|
bool isS6_Immediate(const int value) const;
|
||||||
|
|
||||||
bool isSaveCalleeSavedRegsCall(const MachineInstr* MI) const;
|
|
||||||
bool isConditionalTransfer(const MachineInstr* MI) const;
|
bool isConditionalTransfer(const MachineInstr* MI) const;
|
||||||
bool isConditionalALU32 (const MachineInstr* MI) const;
|
bool isConditionalALU32(const MachineInstr* MI) const;
|
||||||
bool isConditionalLoad (const MachineInstr* MI) const;
|
bool isConditionalLoad(const MachineInstr* MI) const;
|
||||||
bool isConditionalStore(const MachineInstr* MI) const;
|
bool isConditionalStore(const MachineInstr* MI) const;
|
||||||
bool isDeallocRet(const MachineInstr *MI) const;
|
bool isDeallocRet(const MachineInstr *MI) const;
|
||||||
unsigned getInvertedPredicatedOpcode(const int Opc) const;
|
|
||||||
bool isExtendable(const MachineInstr* MI) const;
|
|
||||||
bool isExtended(const MachineInstr* MI) const;
|
|
||||||
bool isPostIncrement(const MachineInstr* MI) const;
|
|
||||||
bool isNewValueStore(const MachineInstr* MI) const;
|
|
||||||
bool isNewValueJump(const MachineInstr* MI) const;
|
|
||||||
bool isNewValueJumpCandidate(const MachineInstr *MI) const;
|
bool isNewValueJumpCandidate(const MachineInstr *MI) const;
|
||||||
unsigned getImmExtForm(const MachineInstr* MI) const;
|
bool isNewValueJump(const MachineInstr* MI) const;
|
||||||
unsigned getNormalBranchForm(const MachineInstr* MI) const;
|
bool isNewValueStore(const MachineInstr* MI) const;
|
||||||
|
bool isPostIncrement(const MachineInstr* MI) const;
|
||||||
|
bool isSaveCalleeSavedRegsCall(const MachineInstr* MI) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int getMatchingCondBranchOpcode(int Opc, bool sense) const;
|
int getMatchingCondBranchOpcode(int Opc, bool sense) const;
|
||||||
|
File diff suppressed because it is too large
Load Diff
626
lib/Target/Hexagon/HexagonInstrInfoV5.td
Normal file
626
lib/Target/Hexagon/HexagonInstrInfoV5.td
Normal file
@ -0,0 +1,626 @@
|
|||||||
|
def SDTHexagonFCONST32 : SDTypeProfile<1, 1, [
|
||||||
|
SDTCisVT<0, f32>,
|
||||||
|
SDTCisPtrTy<1>]>;
|
||||||
|
def HexagonFCONST32 : SDNode<"HexagonISD::FCONST32", SDTHexagonFCONST32>;
|
||||||
|
|
||||||
|
let isReMaterializable = 1, isMoveImm = 1 in
|
||||||
|
def FCONST32_nsdata : LDInst<(outs IntRegs:$dst), (ins globaladdress:$global),
|
||||||
|
"$dst = CONST32(#$global)",
|
||||||
|
[(set (f32 IntRegs:$dst),
|
||||||
|
(HexagonFCONST32 tglobaladdr:$global))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isReMaterializable = 1, isMoveImm = 1 in
|
||||||
|
def CONST64_Float_Real : LDInst<(outs DoubleRegs:$dst), (ins f64imm:$src1),
|
||||||
|
"$dst = CONST64(#$src1)",
|
||||||
|
[(set DoubleRegs:$dst, fpimm:$src1)]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isReMaterializable = 1, isMoveImm = 1 in
|
||||||
|
def CONST32_Float_Real : LDInst<(outs IntRegs:$dst), (ins f32imm:$src1),
|
||||||
|
"$dst = CONST32(#$src1)",
|
||||||
|
[(set IntRegs:$dst, fpimm:$src1)]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Transfer immediate float.
|
||||||
|
// Only works with single precision fp value.
|
||||||
|
// For double precision, use CONST64_float_real, as 64bit transfer
|
||||||
|
// can only hold 40-bit values - 32 from const ext + 8 bit immediate.
|
||||||
|
let isMoveImm = 1, isReMaterializable = 1, isPredicable = 1 in
|
||||||
|
def TFRI_f : ALU32_ri<(outs IntRegs:$dst), (ins f32imm:$src1),
|
||||||
|
"$dst = ##$src1",
|
||||||
|
[(set IntRegs:$dst, fpimm:$src1)]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def TFRI_cPt_f : ALU32_ri<(outs IntRegs:$dst),
|
||||||
|
(ins PredRegs:$src1, f32imm:$src2),
|
||||||
|
"if ($src1) $dst = ##$src2",
|
||||||
|
[]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isPredicated = 1 in
|
||||||
|
def TFRI_cNotPt_f : ALU32_ri<(outs IntRegs:$dst),
|
||||||
|
(ins PredRegs:$src1, f32imm:$src2),
|
||||||
|
"if (!$src1) $dst = ##$src2",
|
||||||
|
[]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Convert single precision to double precision and vice-versa.
|
||||||
|
def CONVERT_sf2df : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2df($src)",
|
||||||
|
[(set DoubleRegs:$dst, (fextend IntRegs:$src))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_df2sf : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2sf($src)",
|
||||||
|
[(set IntRegs:$dst, (fround DoubleRegs:$src))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
// Load.
|
||||||
|
def LDrid_f : LDInst<(outs DoubleRegs:$dst),
|
||||||
|
(ins MEMri:$addr),
|
||||||
|
"$dst = memd($addr)",
|
||||||
|
[(set DoubleRegs:$dst, (f64 (load ADDRriS11_3:$addr)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def LDrid_indexed_f : LDInst<(outs DoubleRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, s11_3Imm:$offset),
|
||||||
|
"$dst = memd($src1+#$offset)",
|
||||||
|
[(set DoubleRegs:$dst, (f64 (load (add IntRegs:$src1,
|
||||||
|
s11_3ImmPred:$offset))))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def LDriw_f : LDInst<(outs IntRegs:$dst),
|
||||||
|
(ins MEMri:$addr), "$dst = memw($addr)",
|
||||||
|
[(set IntRegs:$dst, (f32 (load ADDRriS11_2:$addr)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def LDriw_indexed_f : LDInst<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, s11_2Imm:$offset),
|
||||||
|
"$dst = memw($src1+#$offset)",
|
||||||
|
[(set IntRegs:$dst, (f32 (load (add IntRegs:$src1,
|
||||||
|
s11_2ImmPred:$offset))))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Store.
|
||||||
|
def STriw_f : STInst<(outs),
|
||||||
|
(ins MEMri:$addr, IntRegs:$src1),
|
||||||
|
"memw($addr) = $src1",
|
||||||
|
[(store (f32 IntRegs:$src1), ADDRriS11_2:$addr)]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 10 in
|
||||||
|
def STriw_indexed_f : STInst<(outs),
|
||||||
|
(ins IntRegs:$src1, s11_2Imm:$src2, IntRegs:$src3),
|
||||||
|
"memw($src1+#$src2) = $src3",
|
||||||
|
[(store (f32 IntRegs:$src3),
|
||||||
|
(add IntRegs:$src1, s11_2ImmPred:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def STrid_f : STInst<(outs),
|
||||||
|
(ins MEMri:$addr, DoubleRegs:$src1),
|
||||||
|
"memd($addr) = $src1",
|
||||||
|
[(store (f64 DoubleRegs:$src1), ADDRriS11_2:$addr)]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Indexed store double word.
|
||||||
|
let AddedComplexity = 10 in
|
||||||
|
def STrid_indexed_f : STInst<(outs),
|
||||||
|
(ins IntRegs:$src1, s11_3Imm:$src2, DoubleRegs:$src3),
|
||||||
|
"memd($src1+#$src2) = $src3",
|
||||||
|
[(store (f64 DoubleRegs:$src3),
|
||||||
|
(add IntRegs:$src1, s11_3ImmPred:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
// Add
|
||||||
|
let isCommutable = 1 in
|
||||||
|
def fADD_rr : ALU64_rr<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
"$dst = sfadd($src1, $src2)",
|
||||||
|
[(set IntRegs:$dst, (fadd IntRegs:$src1, IntRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isCommutable = 1 in
|
||||||
|
def fADD64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2),
|
||||||
|
"$dst = dfadd($src1, $src2)",
|
||||||
|
[(set DoubleRegs:$dst, (fadd DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def fSUB_rr : ALU64_rr<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
"$dst = sfsub($src1, $src2)",
|
||||||
|
[(set IntRegs:$dst, (fsub IntRegs:$src1, IntRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def fSUB64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2),
|
||||||
|
"$dst = dfsub($src1, $src2)",
|
||||||
|
[(set DoubleRegs:$dst, (fsub DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isCommutable = 1 in
|
||||||
|
def fMUL_rr : ALU64_rr<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
"$dst = sfmpy($src1, $src2)",
|
||||||
|
[(set IntRegs:$dst, (fmul IntRegs:$src1, IntRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let isCommutable = 1 in
|
||||||
|
def fMUL64_rr : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2),
|
||||||
|
"$dst = dfmpy($src1, $src2)",
|
||||||
|
[(set DoubleRegs:$dst, (fmul DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Compare.
|
||||||
|
let isCompare = 1 in {
|
||||||
|
multiclass FCMP64_rr<string OpcStr, PatFrag OpNode> {
|
||||||
|
def _rr : ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$b, DoubleRegs:$c),
|
||||||
|
!strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
|
||||||
|
[(set PredRegs:$dst,
|
||||||
|
(OpNode (f64 DoubleRegs:$b), (f64 DoubleRegs:$c)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
multiclass FCMP32_rr<string OpcStr, PatFrag OpNode> {
|
||||||
|
def _rr : ALU64_rr<(outs PredRegs:$dst), (ins IntRegs:$b, IntRegs:$c),
|
||||||
|
!strconcat("$dst = ", !strconcat(OpcStr, "($b, $c)")),
|
||||||
|
[(set PredRegs:$dst,
|
||||||
|
(OpNode (f32 IntRegs:$b), (f32 IntRegs:$c)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defm FCMPOEQ64 : FCMP64_rr<"dfcmp.eq", setoeq>;
|
||||||
|
defm FCMPUEQ64 : FCMP64_rr<"dfcmp.eq", setueq>;
|
||||||
|
defm FCMPOGT64 : FCMP64_rr<"dfcmp.gt", setogt>;
|
||||||
|
defm FCMPUGT64 : FCMP64_rr<"dfcmp.gt", setugt>;
|
||||||
|
defm FCMPOGE64 : FCMP64_rr<"dfcmp.ge", setoge>;
|
||||||
|
defm FCMPUGE64 : FCMP64_rr<"dfcmp.ge", setuge>;
|
||||||
|
|
||||||
|
defm FCMPOEQ32 : FCMP32_rr<"sfcmp.eq", setoeq>;
|
||||||
|
defm FCMPUEQ32 : FCMP32_rr<"sfcmp.eq", setueq>;
|
||||||
|
defm FCMPOGT32 : FCMP32_rr<"sfcmp.gt", setogt>;
|
||||||
|
defm FCMPUGT32 : FCMP32_rr<"sfcmp.gt", setugt>;
|
||||||
|
defm FCMPOGE32 : FCMP32_rr<"sfcmp.ge", setoge>;
|
||||||
|
defm FCMPUGE32 : FCMP32_rr<"sfcmp.ge", setuge>;
|
||||||
|
|
||||||
|
// olt.
|
||||||
|
def : Pat <(i1 (setolt (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (FCMPOGT32_rr IntRegs:$src2, IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setolt (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPOGT32_rr (f32 (TFRI_f fpimm:$src2)), (f32 IntRegs:$src1)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setolt (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (FCMPOGT64_rr DoubleRegs:$src2, DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setolt (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPOGT64_rr (f64 (CONST64_Float_Real fpimm:$src2)),
|
||||||
|
(f64 DoubleRegs:$src1)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// gt.
|
||||||
|
def : Pat <(i1 (setugt (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGT64_rr (f64 DoubleRegs:$src1),
|
||||||
|
(f64 (CONST64_Float_Real fpimm:$src2))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setugt (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGT32_rr (f32 IntRegs:$src1), (f32 (TFRI_f fpimm:$src2))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// ult.
|
||||||
|
def : Pat <(i1 (setult (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (FCMPUGT32_rr IntRegs:$src2, IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setult (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGT32_rr (f32 (TFRI_f fpimm:$src2)), (f32 IntRegs:$src1)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setult (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (FCMPUGT64_rr DoubleRegs:$src2, DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i1 (setult (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGT64_rr (f64 (CONST64_Float_Real fpimm:$src2)),
|
||||||
|
(f64 DoubleRegs:$src1)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// le.
|
||||||
|
// rs <= rt -> rt >= rs.
|
||||||
|
def : Pat<(i1 (setole (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (FCMPOGE32_rr IntRegs:$src2, IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setole (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPOGE32_rr (f32 (TFRI_f fpimm:$src2)), IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
// Rss <= Rtt -> Rtt >= Rss.
|
||||||
|
def : Pat<(i1 (setole (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (FCMPOGE64_rr DoubleRegs:$src2, DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setole (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPOGE64_rr (f64 (CONST64_Float_Real fpimm:$src2)),
|
||||||
|
DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// rs <= rt -> rt >= rs.
|
||||||
|
def : Pat<(i1 (setule (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (FCMPUGE32_rr IntRegs:$src2, IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setule (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGE32_rr (f32 (TFRI_f fpimm:$src2)), IntRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Rss <= Rtt -> Rtt >= Rss.
|
||||||
|
def : Pat<(i1 (setule (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (FCMPUGE64_rr DoubleRegs:$src2, DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setule (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (FCMPUGE64_rr (f64 (CONST64_Float_Real fpimm:$src2)),
|
||||||
|
DoubleRegs:$src1))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// ne.
|
||||||
|
def : Pat<(i1 (setone (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPOEQ32_rr IntRegs:$src1, IntRegs:$src2)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setone (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPOEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setune (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPUEQ32_rr IntRegs:$src1, IntRegs:$src2)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setune (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPUEQ64_rr DoubleRegs:$src1, DoubleRegs:$src2)))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setone (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPOEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setone (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPOEQ64_rr DoubleRegs:$src1,
|
||||||
|
(f64 (CONST64_Float_Real fpimm:$src2)))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setune (f32 IntRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPUEQ32_rr IntRegs:$src1, (f32 (TFRI_f fpimm:$src2)))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat<(i1 (setune (f64 DoubleRegs:$src1), (fpimm:$src2))),
|
||||||
|
(i1 (NOT_p (FCMPUEQ64_rr DoubleRegs:$src1,
|
||||||
|
(f64 (CONST64_Float_Real fpimm:$src2)))))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Convert Integer to Floating Point.
|
||||||
|
def CONVERT_d2sf : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_d2sf($src)",
|
||||||
|
[(set (f32 IntRegs:$dst), (sint_to_fp (i64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_ud2sf : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_ud2sf($src)",
|
||||||
|
[(set (f32 IntRegs:$dst), (uint_to_fp (i64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_uw2sf : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_uw2sf($src)",
|
||||||
|
[(set (f32 IntRegs:$dst), (uint_to_fp (i32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_w2sf : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_w2sf($src)",
|
||||||
|
[(set (f32 IntRegs:$dst), (sint_to_fp (i32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_d2df : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_d2df($src)",
|
||||||
|
[(set (f64 DoubleRegs:$dst), (sint_to_fp (i64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_ud2df : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_ud2df($src)",
|
||||||
|
[(set (f64 DoubleRegs:$dst), (uint_to_fp (i64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_uw2df : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_uw2df($src)",
|
||||||
|
[(set (f64 DoubleRegs:$dst), (uint_to_fp (i32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_w2df : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_w2df($src)",
|
||||||
|
[(set (f64 DoubleRegs:$dst), (sint_to_fp (i32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Convert Floating Point to Integer - default.
|
||||||
|
def CONVERT_df2uw : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2uw($src):chop",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_uint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_df2w : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2w($src):chop",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_sint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_sf2uw : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2uw($src):chop",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_uint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_sf2w : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2w($src):chop",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_sint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_df2d : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2d($src):chop",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_sint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_df2ud : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2ud($src):chop",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_uint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_sf2d : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2d($src):chop",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_sint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def CONVERT_sf2ud : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2ud($src):chop",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_uint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Convert Floating Point to Integer: non-chopped.
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_df2uw_nchop : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2uw($src)",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_uint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_df2w_nchop : ALU64_rr<(outs IntRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2w($src)",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_sint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_sf2uw_nchop : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2uw($src)",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_uint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_sf2w_nchop : ALU64_rr<(outs IntRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2w($src)",
|
||||||
|
[(set (i32 IntRegs:$dst), (fp_to_sint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_df2d_nchop : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2d($src)",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_sint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_df2ud_nchop : ALU64_rr<(outs DoubleRegs:$dst), (ins DoubleRegs:$src),
|
||||||
|
"$dst = convert_df2ud($src)",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_uint (f64 DoubleRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_sf2d_nchop : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2d($src)",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_sint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 20 in
|
||||||
|
def CONVERT_sf2ud_nchop : ALU64_rr<(outs DoubleRegs:$dst), (ins IntRegs:$src),
|
||||||
|
"$dst = convert_sf2ud($src)",
|
||||||
|
[(set (i64 DoubleRegs:$dst), (fp_to_uint (f32 IntRegs:$src)))]>,
|
||||||
|
Requires<[HasV5T, IEEERndNearV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Bitcast is different than [fp|sint|uint]_to_[sint|uint|fp].
|
||||||
|
def : Pat <(i32 (bitconvert (f32 IntRegs:$src))),
|
||||||
|
(i32 (TFR IntRegs:$src))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(f32 (bitconvert (i32 IntRegs:$src))),
|
||||||
|
(f32 (TFR IntRegs:$src))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(i64 (bitconvert (f64 DoubleRegs:$src))),
|
||||||
|
(i64 (TFR64 DoubleRegs:$src))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(f64 (bitconvert (i64 DoubleRegs:$src))),
|
||||||
|
(f64 (TFR64 DoubleRegs:$src))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Floating point fused multiply-add.
|
||||||
|
def FMADD_dp : ALU64_acc<(outs DoubleRegs:$dst),
|
||||||
|
(ins DoubleRegs:$src1, DoubleRegs:$src2, DoubleRegs:$src3),
|
||||||
|
"$dst += dfmpy($src2, $src3)",
|
||||||
|
[(set (f64 DoubleRegs:$dst),
|
||||||
|
(fma DoubleRegs:$src2, DoubleRegs:$src3, DoubleRegs:$src1))],
|
||||||
|
"$src1 = $dst">,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def FMADD_sp : ALU64_acc<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2, IntRegs:$src3),
|
||||||
|
"$dst += sfmpy($src2, $src3)",
|
||||||
|
[(set (f32 IntRegs:$dst),
|
||||||
|
(fma IntRegs:$src2, IntRegs:$src3, IntRegs:$src1))],
|
||||||
|
"$src1 = $dst">,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
// Floating point max/min.
|
||||||
|
let AddedComplexity = 100 in
|
||||||
|
def FMAX_dp : ALU64_rr<(outs DoubleRegs:$dst),
|
||||||
|
(ins DoubleRegs:$src1, DoubleRegs:$src2),
|
||||||
|
"$dst = dfmax($src1, $src2)",
|
||||||
|
[(set DoubleRegs:$dst, (f64 (select (i1 (setolt DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$src1)),
|
||||||
|
DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100 in
|
||||||
|
def FMAX_sp : ALU64_rr<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
"$dst = sfmax($src1, $src2)",
|
||||||
|
[(set IntRegs:$dst, (f32 (select (i1 (setolt IntRegs:$src2,
|
||||||
|
IntRegs:$src1)),
|
||||||
|
IntRegs:$src1,
|
||||||
|
IntRegs:$src2)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100 in
|
||||||
|
def FMIN_dp : ALU64_rr<(outs DoubleRegs:$dst),
|
||||||
|
(ins DoubleRegs:$src1, DoubleRegs:$src2),
|
||||||
|
"$dst = dfmin($src1, $src2)",
|
||||||
|
[(set DoubleRegs:$dst, (f64 (select (i1 (setogt DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$src1)),
|
||||||
|
DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100 in
|
||||||
|
def FMIN_sp : ALU64_rr<(outs IntRegs:$dst),
|
||||||
|
(ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
"$dst = sfmin($src1, $src2)",
|
||||||
|
[(set IntRegs:$dst, (f32 (select (i1 (setogt IntRegs:$src2,
|
||||||
|
IntRegs:$src1)),
|
||||||
|
IntRegs:$src1,
|
||||||
|
IntRegs:$src2)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Pseudo instruction to encode a set of conditional transfers.
|
||||||
|
// This instruction is used instead of a mux and trades-off codesize
|
||||||
|
// for performance. We conduct this transformation optimistically in
|
||||||
|
// the hope that these instructions get promoted to dot-new transfers.
|
||||||
|
let AddedComplexity = 100, isPredicated = 1 in
|
||||||
|
def TFR_condset_rr_f : ALU32_rr<(outs IntRegs:$dst), (ins PredRegs:$src1,
|
||||||
|
IntRegs:$src2,
|
||||||
|
IntRegs:$src3),
|
||||||
|
"Error; should not emit",
|
||||||
|
[(set IntRegs:$dst, (f32 (select PredRegs:$src1,
|
||||||
|
IntRegs:$src2,
|
||||||
|
IntRegs:$src3)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100, isPredicated = 1 in
|
||||||
|
def TFR_condset_rr64_f : ALU32_rr<(outs DoubleRegs:$dst), (ins PredRegs:$src1,
|
||||||
|
DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$src3),
|
||||||
|
"Error; should not emit",
|
||||||
|
[(set DoubleRegs:$dst, (f64 (select PredRegs:$src1,
|
||||||
|
DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$src3)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let AddedComplexity = 100, isPredicated = 1 in
|
||||||
|
def TFR_condset_ri_f : ALU32_rr<(outs IntRegs:$dst),
|
||||||
|
(ins PredRegs:$src1, IntRegs:$src2, f32imm:$src3),
|
||||||
|
"Error; should not emit",
|
||||||
|
[(set IntRegs:$dst,
|
||||||
|
(f32 (select PredRegs:$src1, IntRegs:$src2, fpimm:$src3)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100, isPredicated = 1 in
|
||||||
|
def TFR_condset_ir_f : ALU32_rr<(outs IntRegs:$dst),
|
||||||
|
(ins PredRegs:$src1, f32imm:$src2, IntRegs:$src3),
|
||||||
|
"Error; should not emit",
|
||||||
|
[(set IntRegs:$dst,
|
||||||
|
(f32 (select PredRegs:$src1, fpimm:$src2, IntRegs:$src3)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
let AddedComplexity = 100, isPredicated = 1 in
|
||||||
|
def TFR_condset_ii_f : ALU32_rr<(outs IntRegs:$dst),
|
||||||
|
(ins PredRegs:$src1, f32imm:$src2, f32imm:$src3),
|
||||||
|
"Error; should not emit",
|
||||||
|
[(set IntRegs:$dst, (f32 (select PredRegs:$src1,
|
||||||
|
fpimm:$src2,
|
||||||
|
fpimm:$src3)))]>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
|
||||||
|
def : Pat <(select (i1 (setult (f32 IntRegs:$src1), (f32 IntRegs:$src2))),
|
||||||
|
(f32 IntRegs:$src3),
|
||||||
|
(f32 IntRegs:$src4)),
|
||||||
|
(TFR_condset_rr_f (FCMPUGT32_rr IntRegs:$src2, IntRegs:$src1), IntRegs:$src4,
|
||||||
|
IntRegs:$src3)>, Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(select (i1 (setult (f64 DoubleRegs:$src1), (f64 DoubleRegs:$src2))),
|
||||||
|
(f64 DoubleRegs:$src3),
|
||||||
|
(f64 DoubleRegs:$src4)),
|
||||||
|
(TFR_condset_rr64_f (FCMPUGT64_rr DoubleRegs:$src2, DoubleRegs:$src1),
|
||||||
|
DoubleRegs:$src4, DoubleRegs:$src3)>, Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
// Map from p0 = pnot(p0); r0 = mux(p0, #i, #j) => r0 = mux(p0, #j, #i).
|
||||||
|
def : Pat <(select (not PredRegs:$src1), fpimm:$src2, fpimm:$src3),
|
||||||
|
(TFR_condset_ii_f PredRegs:$src1, fpimm:$src3, fpimm:$src2)>;
|
||||||
|
|
||||||
|
// Map from p0 = pnot(p0); r0 = select(p0, #i, r1)
|
||||||
|
// => r0 = TFR_condset_ri(p0, r1, #i)
|
||||||
|
def : Pat <(select (not PredRegs:$src1), fpimm:$src2, IntRegs:$src3),
|
||||||
|
(TFR_condset_ri_f PredRegs:$src1, IntRegs:$src3, fpimm:$src2)>;
|
||||||
|
|
||||||
|
// Map from p0 = pnot(p0); r0 = mux(p0, r1, #i)
|
||||||
|
// => r0 = TFR_condset_ir(p0, #i, r1)
|
||||||
|
def : Pat <(select (not PredRegs:$src1), IntRegs:$src2, fpimm:$src3),
|
||||||
|
(TFR_condset_ir_f PredRegs:$src1, fpimm:$src3, IntRegs:$src2)>;
|
||||||
|
|
||||||
|
def : Pat <(i32 (fp_to_sint (f64 DoubleRegs:$src1))),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 (CONVERT_df2d (f64 DoubleRegs:$src1))), subreg_loreg))>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(fabs (f32 IntRegs:$src1)),
|
||||||
|
(CLRBIT_31 (f32 IntRegs:$src1), 31)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(fneg (f32 IntRegs:$src1)),
|
||||||
|
(TOGBIT_31 (f32 IntRegs:$src1), 31)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
/*
|
||||||
|
def : Pat <(fabs (f64 DoubleRegs:$src1)),
|
||||||
|
(CLRBIT_31 (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
|
||||||
|
def : Pat <(fabs (f64 DoubleRegs:$src1)),
|
||||||
|
(CLRBIT_31 (f32 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)), 31)>,
|
||||||
|
Requires<[HasV5T]>;
|
||||||
|
*/
|
File diff suppressed because it is too large
Load Diff
@ -12,18 +12,28 @@
|
|||||||
// Optimized with intrinisics accumulates
|
// Optimized with intrinisics accumulates
|
||||||
//
|
//
|
||||||
def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2),
|
def : Pat <(mul DoubleRegs:$src1, DoubleRegs:$src2),
|
||||||
(COMBINE_rr
|
(i64
|
||||||
(Hexagon_M2_maci
|
(COMBINE_rr
|
||||||
(Hexagon_M2_maci (EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
(HEXAGON_M2_maci
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)),
|
(HEXAGON_M2_maci
|
||||||
subreg_hireg),
|
(i32
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
(EXTRACT_SUBREG
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_hireg)),
|
(i64
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg),
|
(MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1),
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src1, subreg_hireg)),
|
subreg_loreg)),
|
||||||
(EXTRACT_SUBREG (MPYU64 (EXTRACT_SUBREG DoubleRegs:$src1, subreg_loreg),
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
|
||||||
(EXTRACT_SUBREG DoubleRegs:$src2, subreg_loreg)),
|
subreg_loreg)))),
|
||||||
subreg_loreg))>;
|
subreg_hireg)),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_hireg))),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2), subreg_loreg)),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_hireg))),
|
||||||
|
(i32
|
||||||
|
(EXTRACT_SUBREG
|
||||||
|
(i64
|
||||||
|
(MPYU64 (i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src1), subreg_loreg)),
|
||||||
|
(i32 (EXTRACT_SUBREG (i64 DoubleRegs:$src2),
|
||||||
|
subreg_loreg)))), subreg_loreg))))>;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
395
lib/Target/Hexagon/HexagonIntrinsicsV5.td
Normal file
395
lib/Target/Hexagon/HexagonIntrinsicsV5.td
Normal file
@ -0,0 +1,395 @@
|
|||||||
|
class sf_SInst_sf<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class si_SInst_sf<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class sf_SInst_si<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class sf_SInst_di<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
class sf_SInst_df<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
class si_SInst_df<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set IntRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
class df_SInst_sf<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class di_SInst_sf<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class df_SInst_si<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins IntRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID IntRegs:$src1))]>;
|
||||||
|
|
||||||
|
class df_SInst_df<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
class di_SInst_df<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
|
||||||
|
class df_SInst_di<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1))]>;
|
||||||
|
|
||||||
|
class sf_MInst_sfsf<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||||
|
|
||||||
|
class df_MInst_dfdf<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>;
|
||||||
|
|
||||||
|
class qi_ALU64_dfdf<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_rr<(outs PredRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")),
|
||||||
|
[(set PredRegs:$dst, (IntID DoubleRegs:$src1, DoubleRegs:$src2))]>;
|
||||||
|
|
||||||
|
class qi_ALU64_dfu5<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_ri<(outs PredRegs:$dst), (ins DoubleRegs:$src1, u5Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")),
|
||||||
|
[(set PredRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
|
||||||
|
class sf_MInst_sfsfsf_acc<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||||
|
IntRegs:$dst2),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class sf_MInst_sfsfsf_nac<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||||
|
IntRegs:$dst2),
|
||||||
|
!strconcat("$dst -= ", !strconcat(opc ,
|
||||||
|
"($src1, $src2)")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
|
||||||
|
class sf_MInst_sfsfsfsi_sc<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$dst2, IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$src3),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2, $src3):scale")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$dst2, IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$src3))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class sf_MInst_sfsfsf_acc_lib<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||||
|
IntRegs:$dst2),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2):lib")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class sf_MInst_sfsfsf_nac_lib<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs IntRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2,
|
||||||
|
IntRegs:$dst2),
|
||||||
|
!strconcat("$dst -= ", !strconcat(opc ,
|
||||||
|
"($src1, $src2):lib")),
|
||||||
|
[(set IntRegs:$dst, (IntID IntRegs:$src1,
|
||||||
|
IntRegs:$src2, IntRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class df_MInst_dfdfdf_acc<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$dst2),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, DoubleRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class df_MInst_dfdfdf_nac<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$dst2),
|
||||||
|
!strconcat("$dst -= ", !strconcat(opc ,
|
||||||
|
"($src1, $src2)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, DoubleRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
|
||||||
|
class df_MInst_dfdfdfsi_sc<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$dst2, DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, IntRegs:$src3),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2, $src3):scale")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$dst2, DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, IntRegs:$src3))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class df_MInst_dfdfdf_acc_lib<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$dst2),
|
||||||
|
!strconcat("$dst += ", !strconcat(opc ,
|
||||||
|
"($src1, $src2):lib")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, DoubleRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class df_MInst_dfdfdf_nac_lib<string opc, Intrinsic IntID>
|
||||||
|
: MInst_acc<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, DoubleRegs:$src2,
|
||||||
|
DoubleRegs:$dst2),
|
||||||
|
!strconcat("$dst -= ", !strconcat(opc ,
|
||||||
|
"($src1, $src2):lib")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1,
|
||||||
|
DoubleRegs:$src2, DoubleRegs:$dst2))],
|
||||||
|
"$dst2 = $dst">;
|
||||||
|
|
||||||
|
class qi_SInst_sfsf<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs PredRegs:$dst), (ins IntRegs:$src1, IntRegs:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, $src2)")),
|
||||||
|
[(set PredRegs:$dst, (IntID IntRegs:$src1, IntRegs:$src2))]>;
|
||||||
|
|
||||||
|
class qi_SInst_sfu5<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs PredRegs:$dst), (ins IntRegs:$src1, u5Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")),
|
||||||
|
[(set PredRegs:$dst, (IntID IntRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
class sf_ALU64_u10_pos<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_ri<(outs IntRegs:$dst), (ins u10Imm:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "#$src1):pos")),
|
||||||
|
[(set IntRegs:$dst, (IntID imm:$src1))]>;
|
||||||
|
|
||||||
|
class sf_ALU64_u10_neg<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_ri<(outs IntRegs:$dst), (ins u10Imm:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "#$src1):neg")),
|
||||||
|
[(set IntRegs:$dst, (IntID imm:$src1))]>;
|
||||||
|
|
||||||
|
class df_ALU64_u10_pos<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_ri<(outs DoubleRegs:$dst), (ins u10Imm:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "#$src1):pos")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID imm:$src1))]>;
|
||||||
|
|
||||||
|
class df_ALU64_u10_neg<string opc, Intrinsic IntID>
|
||||||
|
: ALU64_ri<(outs DoubleRegs:$dst), (ins u10Imm:$src1),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "#$src1):neg")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID imm:$src1))]>;
|
||||||
|
|
||||||
|
class di_MInst_diu6<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u6Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2)")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
class di_MInst_diu4_rnd<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs DoubleRegs:$dst), (ins DoubleRegs:$src1, u4Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):rnd")),
|
||||||
|
[(set DoubleRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
class si_MInst_diu4_rnd_sat<string opc, Intrinsic IntID>
|
||||||
|
: MInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, u4Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):rnd:sat")),
|
||||||
|
[(set IntRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
class si_SInst_diu4_sat<string opc, Intrinsic IntID>
|
||||||
|
: SInst<(outs IntRegs:$dst), (ins DoubleRegs:$src1, u4Imm:$src2),
|
||||||
|
!strconcat("$dst = ", !strconcat(opc , "($src1, #$src2):sat")),
|
||||||
|
[(set IntRegs:$dst, (IntID DoubleRegs:$src1, imm:$src2))]>;
|
||||||
|
|
||||||
|
|
||||||
|
def HEXAGON_C4_fastcorner9:
|
||||||
|
qi_SInst_qiqi <"fastcorner9", int_hexagon_C4_fastcorner9>;
|
||||||
|
def HEXAGON_C4_fastcorner9_not:
|
||||||
|
qi_SInst_qiqi <"!fastcorner9", int_hexagon_C4_fastcorner9_not>;
|
||||||
|
def HEXAGON_M5_vrmpybuu:
|
||||||
|
di_MInst_didi <"vrmpybu", int_hexagon_M5_vrmpybuu>;
|
||||||
|
def HEXAGON_M5_vrmacbuu:
|
||||||
|
di_MInst_dididi_acc <"vrmpybu", int_hexagon_M5_vrmacbuu>;
|
||||||
|
def HEXAGON_M5_vrmpybsu:
|
||||||
|
di_MInst_didi <"vrmpybsu", int_hexagon_M5_vrmpybsu>;
|
||||||
|
def HEXAGON_M5_vrmacbsu:
|
||||||
|
di_MInst_dididi_acc <"vrmpybsu", int_hexagon_M5_vrmacbsu>;
|
||||||
|
def HEXAGON_M5_vmpybuu:
|
||||||
|
di_MInst_sisi <"vmpybu", int_hexagon_M5_vmpybuu>;
|
||||||
|
def HEXAGON_M5_vmpybsu:
|
||||||
|
di_MInst_sisi <"vmpybsu", int_hexagon_M5_vmpybsu>;
|
||||||
|
def HEXAGON_M5_vmacbuu:
|
||||||
|
di_MInst_disisi_acc <"vmpybu", int_hexagon_M5_vmacbuu>;
|
||||||
|
def HEXAGON_M5_vmacbsu:
|
||||||
|
di_MInst_disisi_acc <"vmpybsu", int_hexagon_M5_vmacbsu>;
|
||||||
|
def HEXAGON_M5_vdmpybsu:
|
||||||
|
di_MInst_didi_sat <"vdmpybsu", int_hexagon_M5_vdmpybsu>;
|
||||||
|
def HEXAGON_M5_vdmacbsu:
|
||||||
|
di_MInst_dididi_acc_sat <"vdmpybsu", int_hexagon_M5_vdmacbsu>;
|
||||||
|
def HEXAGON_A5_vaddhubs:
|
||||||
|
si_SInst_didi_sat <"vaddhub", int_hexagon_A5_vaddhubs>;
|
||||||
|
def HEXAGON_S5_popcountp:
|
||||||
|
si_SInst_di <"popcount", int_hexagon_S5_popcountp>;
|
||||||
|
def HEXAGON_S5_asrhub_rnd_sat_goodsyntax:
|
||||||
|
si_MInst_diu4_rnd_sat <"vasrhub", int_hexagon_S5_asrhub_rnd_sat_goodsyntax>;
|
||||||
|
def HEXAGON_S5_asrhub_sat:
|
||||||
|
si_SInst_diu4_sat <"vasrhub", int_hexagon_S5_asrhub_sat>;
|
||||||
|
def HEXAGON_S5_vasrhrnd_goodsyntax:
|
||||||
|
di_MInst_diu4_rnd <"vasrh", int_hexagon_S5_vasrhrnd_goodsyntax>;
|
||||||
|
def HEXAGON_S2_asr_i_p_rnd:
|
||||||
|
di_SInst_diu6 <"asr", int_hexagon_S2_asr_i_p_rnd>;
|
||||||
|
def HEXAGON_S2_asr_i_p_rnd_goodsyntax:
|
||||||
|
di_MInst_diu6 <"asrrnd", int_hexagon_S2_asr_i_p_rnd_goodsyntax>;
|
||||||
|
def HEXAGON_F2_sfadd:
|
||||||
|
sf_MInst_sfsf <"sfadd", int_hexagon_F2_sfadd>;
|
||||||
|
def HEXAGON_F2_sfsub:
|
||||||
|
sf_MInst_sfsf <"sfsub", int_hexagon_F2_sfsub>;
|
||||||
|
def HEXAGON_F2_sfmpy:
|
||||||
|
sf_MInst_sfsf <"sfmpy", int_hexagon_F2_sfmpy>;
|
||||||
|
def HEXAGON_F2_sffma:
|
||||||
|
sf_MInst_sfsfsf_acc <"sfmpy", int_hexagon_F2_sffma>;
|
||||||
|
def HEXAGON_F2_sffma_sc:
|
||||||
|
sf_MInst_sfsfsfsi_sc <"sfmpy", int_hexagon_F2_sffma_sc>;
|
||||||
|
def HEXAGON_F2_sffms:
|
||||||
|
sf_MInst_sfsfsf_nac <"sfmpy", int_hexagon_F2_sffms>;
|
||||||
|
def HEXAGON_F2_sffma_lib:
|
||||||
|
sf_MInst_sfsfsf_acc_lib <"sfmpy", int_hexagon_F2_sffma_lib>;
|
||||||
|
def HEXAGON_F2_sffms_lib:
|
||||||
|
sf_MInst_sfsfsf_nac_lib <"sfmpy", int_hexagon_F2_sffms_lib>;
|
||||||
|
def HEXAGON_F2_sfcmpeq:
|
||||||
|
qi_SInst_sfsf <"sfcmp.eq", int_hexagon_F2_sfcmpeq>;
|
||||||
|
def HEXAGON_F2_sfcmpgt:
|
||||||
|
qi_SInst_sfsf <"sfcmp.gt", int_hexagon_F2_sfcmpgt>;
|
||||||
|
def HEXAGON_F2_sfcmpge:
|
||||||
|
qi_SInst_sfsf <"sfcmp.ge", int_hexagon_F2_sfcmpge>;
|
||||||
|
def HEXAGON_F2_sfcmpuo:
|
||||||
|
qi_SInst_sfsf <"sfcmp.uo", int_hexagon_F2_sfcmpuo>;
|
||||||
|
def HEXAGON_F2_sfmax:
|
||||||
|
sf_MInst_sfsf <"sfmax", int_hexagon_F2_sfmax>;
|
||||||
|
def HEXAGON_F2_sfmin:
|
||||||
|
sf_MInst_sfsf <"sfmin", int_hexagon_F2_sfmin>;
|
||||||
|
def HEXAGON_F2_sfclass:
|
||||||
|
qi_SInst_sfu5 <"sfclass", int_hexagon_F2_sfclass>;
|
||||||
|
def HEXAGON_F2_sfimm_p:
|
||||||
|
sf_ALU64_u10_pos <"sfmake", int_hexagon_F2_sfimm_p>;
|
||||||
|
def HEXAGON_F2_sfimm_n:
|
||||||
|
sf_ALU64_u10_neg <"sfmake", int_hexagon_F2_sfimm_n>;
|
||||||
|
def HEXAGON_F2_sffixupn:
|
||||||
|
sf_MInst_sfsf <"sffixupn", int_hexagon_F2_sffixupn>;
|
||||||
|
def HEXAGON_F2_sffixupd:
|
||||||
|
sf_MInst_sfsf <"sffixupd", int_hexagon_F2_sffixupd>;
|
||||||
|
def HEXAGON_F2_sffixupr:
|
||||||
|
sf_SInst_sf <"sffixupr", int_hexagon_F2_sffixupr>;
|
||||||
|
def HEXAGON_F2_dfadd:
|
||||||
|
df_MInst_dfdf <"dfadd", int_hexagon_F2_dfadd>;
|
||||||
|
def HEXAGON_F2_dfsub:
|
||||||
|
df_MInst_dfdf <"dfsub", int_hexagon_F2_dfsub>;
|
||||||
|
def HEXAGON_F2_dfmpy:
|
||||||
|
df_MInst_dfdf <"dfmpy", int_hexagon_F2_dfmpy>;
|
||||||
|
def HEXAGON_F2_dffma:
|
||||||
|
df_MInst_dfdfdf_acc <"dfmpy", int_hexagon_F2_dffma>;
|
||||||
|
def HEXAGON_F2_dffms:
|
||||||
|
df_MInst_dfdfdf_nac <"dfmpy", int_hexagon_F2_dffms>;
|
||||||
|
def HEXAGON_F2_dffma_lib:
|
||||||
|
df_MInst_dfdfdf_acc_lib <"dfmpy", int_hexagon_F2_dffma_lib>;
|
||||||
|
def HEXAGON_F2_dffms_lib:
|
||||||
|
df_MInst_dfdfdf_nac_lib <"dfmpy", int_hexagon_F2_dffms_lib>;
|
||||||
|
def HEXAGON_F2_dffma_sc:
|
||||||
|
df_MInst_dfdfdfsi_sc <"dfmpy", int_hexagon_F2_dffma_sc>;
|
||||||
|
def HEXAGON_F2_dfmax:
|
||||||
|
df_MInst_dfdf <"dfmax", int_hexagon_F2_dfmax>;
|
||||||
|
def HEXAGON_F2_dfmin:
|
||||||
|
df_MInst_dfdf <"dfmin", int_hexagon_F2_dfmin>;
|
||||||
|
def HEXAGON_F2_dfcmpeq:
|
||||||
|
qi_ALU64_dfdf <"dfcmp.eq", int_hexagon_F2_dfcmpeq>;
|
||||||
|
def HEXAGON_F2_dfcmpgt:
|
||||||
|
qi_ALU64_dfdf <"dfcmp.gt", int_hexagon_F2_dfcmpgt>;
|
||||||
|
def HEXAGON_F2_dfcmpge:
|
||||||
|
qi_ALU64_dfdf <"dfcmp.ge", int_hexagon_F2_dfcmpge>;
|
||||||
|
def HEXAGON_F2_dfcmpuo:
|
||||||
|
qi_ALU64_dfdf <"dfcmp.uo", int_hexagon_F2_dfcmpuo>;
|
||||||
|
def HEXAGON_F2_dfclass:
|
||||||
|
qi_ALU64_dfu5 <"dfclass", int_hexagon_F2_dfclass>;
|
||||||
|
def HEXAGON_F2_dfimm_p:
|
||||||
|
df_ALU64_u10_pos <"dfmake", int_hexagon_F2_dfimm_p>;
|
||||||
|
def HEXAGON_F2_dfimm_n:
|
||||||
|
df_ALU64_u10_neg <"dfmake", int_hexagon_F2_dfimm_n>;
|
||||||
|
def HEXAGON_F2_dffixupn:
|
||||||
|
df_MInst_dfdf <"dffixupn", int_hexagon_F2_dffixupn>;
|
||||||
|
def HEXAGON_F2_dffixupd:
|
||||||
|
df_MInst_dfdf <"dffixupd", int_hexagon_F2_dffixupd>;
|
||||||
|
def HEXAGON_F2_dffixupr:
|
||||||
|
df_SInst_df <"dffixupr", int_hexagon_F2_dffixupr>;
|
||||||
|
def HEXAGON_F2_conv_sf2df:
|
||||||
|
df_SInst_sf <"convert_sf2df", int_hexagon_F2_conv_sf2df>;
|
||||||
|
def HEXAGON_F2_conv_df2sf:
|
||||||
|
sf_SInst_df <"convert_df2sf", int_hexagon_F2_conv_df2sf>;
|
||||||
|
def HEXAGON_F2_conv_uw2sf:
|
||||||
|
sf_SInst_si <"convert_uw2sf", int_hexagon_F2_conv_uw2sf>;
|
||||||
|
def HEXAGON_F2_conv_uw2df:
|
||||||
|
df_SInst_si <"convert_uw2df", int_hexagon_F2_conv_uw2df>;
|
||||||
|
def HEXAGON_F2_conv_w2sf:
|
||||||
|
sf_SInst_si <"convert_w2sf", int_hexagon_F2_conv_w2sf>;
|
||||||
|
def HEXAGON_F2_conv_w2df:
|
||||||
|
df_SInst_si <"convert_w2df", int_hexagon_F2_conv_w2df>;
|
||||||
|
def HEXAGON_F2_conv_ud2sf:
|
||||||
|
sf_SInst_di <"convert_ud2sf", int_hexagon_F2_conv_ud2sf>;
|
||||||
|
def HEXAGON_F2_conv_ud2df:
|
||||||
|
df_SInst_di <"convert_ud2df", int_hexagon_F2_conv_ud2df>;
|
||||||
|
def HEXAGON_F2_conv_d2sf:
|
||||||
|
sf_SInst_di <"convert_d2sf", int_hexagon_F2_conv_d2sf>;
|
||||||
|
def HEXAGON_F2_conv_d2df:
|
||||||
|
df_SInst_di <"convert_d2df", int_hexagon_F2_conv_d2df>;
|
||||||
|
def HEXAGON_F2_conv_sf2uw:
|
||||||
|
si_SInst_sf <"convert_sf2uw", int_hexagon_F2_conv_sf2uw>;
|
||||||
|
def HEXAGON_F2_conv_sf2w:
|
||||||
|
si_SInst_sf <"convert_sf2w", int_hexagon_F2_conv_sf2w>;
|
||||||
|
def HEXAGON_F2_conv_sf2ud:
|
||||||
|
di_SInst_sf <"convert_sf2ud", int_hexagon_F2_conv_sf2ud>;
|
||||||
|
def HEXAGON_F2_conv_sf2d:
|
||||||
|
di_SInst_sf <"convert_sf2d", int_hexagon_F2_conv_sf2d>;
|
||||||
|
def HEXAGON_F2_conv_df2uw:
|
||||||
|
si_SInst_df <"convert_df2uw", int_hexagon_F2_conv_df2uw>;
|
||||||
|
def HEXAGON_F2_conv_df2w:
|
||||||
|
si_SInst_df <"convert_df2w", int_hexagon_F2_conv_df2w>;
|
||||||
|
def HEXAGON_F2_conv_df2ud:
|
||||||
|
di_SInst_df <"convert_df2ud", int_hexagon_F2_conv_df2ud>;
|
||||||
|
def HEXAGON_F2_conv_df2d:
|
||||||
|
di_SInst_df <"convert_df2d", int_hexagon_F2_conv_df2d>;
|
||||||
|
def HEXAGON_F2_conv_sf2uw_chop:
|
||||||
|
si_SInst_sf <"convert_sf2uw", int_hexagon_F2_conv_sf2uw_chop>;
|
||||||
|
def HEXAGON_F2_conv_sf2w_chop:
|
||||||
|
si_SInst_sf <"convert_sf2w", int_hexagon_F2_conv_sf2w_chop>;
|
||||||
|
def HEXAGON_F2_conv_sf2ud_chop:
|
||||||
|
di_SInst_sf <"convert_sf2ud", int_hexagon_F2_conv_sf2ud_chop>;
|
||||||
|
def HEXAGON_F2_conv_sf2d_chop:
|
||||||
|
di_SInst_sf <"convert_sf2d", int_hexagon_F2_conv_sf2d_chop>;
|
||||||
|
def HEXAGON_F2_conv_df2uw_chop:
|
||||||
|
si_SInst_df <"convert_df2uw", int_hexagon_F2_conv_df2uw_chop>;
|
||||||
|
def HEXAGON_F2_conv_df2w_chop:
|
||||||
|
si_SInst_df <"convert_df2w", int_hexagon_F2_conv_df2w_chop>;
|
||||||
|
def HEXAGON_F2_conv_df2ud_chop:
|
||||||
|
di_SInst_df <"convert_df2ud", int_hexagon_F2_conv_df2ud_chop>;
|
||||||
|
def HEXAGON_F2_conv_df2d_chop:
|
||||||
|
di_SInst_df <"convert_df2d", int_hexagon_F2_conv_df2d_chop>;
|
@ -63,6 +63,7 @@ const uint16_t* HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction
|
|||||||
return CalleeSavedRegsV2;
|
return CalleeSavedRegsV2;
|
||||||
case HexagonSubtarget::V3:
|
case HexagonSubtarget::V3:
|
||||||
case HexagonSubtarget::V4:
|
case HexagonSubtarget::V4:
|
||||||
|
case HexagonSubtarget::V5:
|
||||||
return CalleeSavedRegsV3;
|
return CalleeSavedRegsV3;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Callee saved registers requested for unknown architecture "
|
llvm_unreachable("Callee saved registers requested for unknown architecture "
|
||||||
@ -109,6 +110,7 @@ HexagonRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
|||||||
return CalleeSavedRegClassesV2;
|
return CalleeSavedRegClassesV2;
|
||||||
case HexagonSubtarget::V3:
|
case HexagonSubtarget::V3:
|
||||||
case HexagonSubtarget::V4:
|
case HexagonSubtarget::V4:
|
||||||
|
case HexagonSubtarget::V5:
|
||||||
return CalleeSavedRegClassesV3;
|
return CalleeSavedRegClassesV3;
|
||||||
}
|
}
|
||||||
llvm_unreachable("Callee saved register classes requested for unknown "
|
llvm_unreachable("Callee saved register classes requested for unknown "
|
||||||
@ -179,11 +181,13 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
// r0 = add(r30, #10000)
|
// r0 = add(r30, #10000)
|
||||||
// r0 = memw(r0)
|
// r0 = memw(r0)
|
||||||
if ( (MI.getOpcode() == Hexagon::LDriw) ||
|
if ( (MI.getOpcode() == Hexagon::LDriw) ||
|
||||||
(MI.getOpcode() == Hexagon::LDrid) ||
|
(MI.getOpcode() == Hexagon::LDrid) ||
|
||||||
(MI.getOpcode() == Hexagon::LDrih) ||
|
(MI.getOpcode() == Hexagon::LDrih) ||
|
||||||
(MI.getOpcode() == Hexagon::LDriuh) ||
|
(MI.getOpcode() == Hexagon::LDriuh) ||
|
||||||
(MI.getOpcode() == Hexagon::LDrib) ||
|
(MI.getOpcode() == Hexagon::LDrib) ||
|
||||||
(MI.getOpcode() == Hexagon::LDriub) ) {
|
(MI.getOpcode() == Hexagon::LDriub) ||
|
||||||
|
(MI.getOpcode() == Hexagon::LDriw_f) ||
|
||||||
|
(MI.getOpcode() == Hexagon::LDrid_f)) {
|
||||||
unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
|
unsigned dstReg = (MI.getOpcode() == Hexagon::LDrid) ?
|
||||||
*getSubRegisters(MI.getOperand(0).getReg()) :
|
*getSubRegisters(MI.getOperand(0).getReg()) :
|
||||||
MI.getOperand(0).getReg();
|
MI.getOperand(0).getReg();
|
||||||
@ -203,10 +207,13 @@ void HexagonRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
|||||||
|
|
||||||
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
|
MI.getOperand(i).ChangeToRegister(dstReg, false, false, true);
|
||||||
MI.getOperand(i+1).ChangeToImmediate(0);
|
MI.getOperand(i+1).ChangeToImmediate(0);
|
||||||
} else if ((MI.getOpcode() == Hexagon::STriw) ||
|
} else if ((MI.getOpcode() == Hexagon::STriw_indexed) ||
|
||||||
|
(MI.getOpcode() == Hexagon::STriw) ||
|
||||||
(MI.getOpcode() == Hexagon::STrid) ||
|
(MI.getOpcode() == Hexagon::STrid) ||
|
||||||
(MI.getOpcode() == Hexagon::STrih) ||
|
(MI.getOpcode() == Hexagon::STrih) ||
|
||||||
(MI.getOpcode() == Hexagon::STrib)) {
|
(MI.getOpcode() == Hexagon::STrib) ||
|
||||||
|
(MI.getOpcode() == Hexagon::STrid_f) ||
|
||||||
|
(MI.getOpcode() == Hexagon::STriw_f)) {
|
||||||
// For stores, we need a reserved register. Change
|
// For stores, we need a reserved register. Change
|
||||||
// memw(r30 + #10000) = r0 to:
|
// memw(r30 + #10000) = r0 to:
|
||||||
//
|
//
|
||||||
|
@ -131,6 +131,9 @@ let Namespace = "Hexagon" in {
|
|||||||
def SA1 : Rc<2, "sa1">, DwarfRegNum<[69]>;
|
def SA1 : Rc<2, "sa1">, DwarfRegNum<[69]>;
|
||||||
def LC1 : Rc<3, "lc1">, DwarfRegNum<[70]>;
|
def LC1 : Rc<3, "lc1">, DwarfRegNum<[70]>;
|
||||||
|
|
||||||
|
def M0 : Rc<6, "m0">, DwarfRegNum<[71]>;
|
||||||
|
def M1 : Rc<7, "m1">, DwarfRegNum<[72]>;
|
||||||
|
|
||||||
def PC : Rc<9, "pc">, DwarfRegNum<[32]>; // is the Dwarf number correct?
|
def PC : Rc<9, "pc">, DwarfRegNum<[32]>; // is the Dwarf number correct?
|
||||||
def GP : Rc<11, "gp">, DwarfRegNum<[33]>; // is the Dwarf number correct?
|
def GP : Rc<11, "gp">, DwarfRegNum<[33]>; // is the Dwarf number correct?
|
||||||
}
|
}
|
||||||
@ -140,15 +143,13 @@ let Namespace = "Hexagon" in {
|
|||||||
// FIXME: the register order should be defined in terms of the preferred
|
// FIXME: the register order should be defined in terms of the preferred
|
||||||
// allocation order...
|
// allocation order...
|
||||||
//
|
//
|
||||||
def IntRegs : RegisterClass<"Hexagon", [i32], 32,
|
def IntRegs : RegisterClass<"Hexagon", [i32,f32], 32,
|
||||||
(add (sequence "R%u", 0, 9),
|
(add (sequence "R%u", 0, 9),
|
||||||
(sequence "R%u", 12, 28),
|
(sequence "R%u", 12, 28),
|
||||||
R10, R11, R29, R30, R31)> {
|
R10, R11, R29, R30, R31)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def DoubleRegs : RegisterClass<"Hexagon", [i64,f64], 64,
|
||||||
|
|
||||||
def DoubleRegs : RegisterClass<"Hexagon", [i64], 64,
|
|
||||||
(add (sequence "D%u", 0, 4),
|
(add (sequence "D%u", 0, 4),
|
||||||
(sequence "D%u", 6, 13), D5, D14, D15)> {
|
(sequence "D%u", 6, 13), D5, D14, D15)> {
|
||||||
let SubRegClasses = [(IntRegs subreg_loreg, subreg_hireg)];
|
let SubRegClasses = [(IntRegs subreg_loreg, subreg_hireg)];
|
||||||
@ -162,6 +163,7 @@ def PredRegs : RegisterClass<"Hexagon", [i1], 32, (add (sequence "P%u", 0, 3))>
|
|||||||
|
|
||||||
def CRRegs : RegisterClass<"Hexagon", [i32], 32,
|
def CRRegs : RegisterClass<"Hexagon", [i32], 32,
|
||||||
(add (sequence "LC%u", 0, 1),
|
(add (sequence "LC%u", 0, 1),
|
||||||
(sequence "SA%u", 0, 1), PC, GP)> {
|
(sequence "SA%u", 0, 1),
|
||||||
|
(sequence "M%u", 0, 1), PC, GP)> {
|
||||||
let Size = 32;
|
let Size = 32;
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// {p0 = cmp.eq(r0,r1)}
|
// {p0 = cmp.eq(r0,r1)}
|
||||||
// {r3 = mux(p0,#1,#3)}
|
// {r3 = mux(p0,#1,#3)}
|
||||||
//
|
//
|
||||||
// This requires two packets. If we use .new predicated immediate transfers,
|
// This requires two packets. If we use .new predicated immediate transfers,
|
||||||
// then we can do this in a single packet, e.g.:
|
// then we can do this in a single packet, e.g.:
|
||||||
//
|
//
|
||||||
// {p0 = cmp.eq(r0,r1)
|
// {p0 = cmp.eq(r0,r1)
|
||||||
@ -81,40 +81,124 @@ bool HexagonSplitTFRCondSets::runOnMachineFunction(MachineFunction &Fn) {
|
|||||||
for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
|
for (MachineBasicBlock::iterator MII = MBB->begin(); MII != MBB->end();
|
||||||
++MII) {
|
++MII) {
|
||||||
MachineInstr *MI = MII;
|
MachineInstr *MI = MII;
|
||||||
int Opc = MI->getOpcode();
|
int Opc1, Opc2;
|
||||||
if (Opc == Hexagon::TFR_condset_rr) {
|
switch(MI->getOpcode()) {
|
||||||
|
case Hexagon::TFR_condset_rr:
|
||||||
|
case Hexagon::TFR_condset_rr_f:
|
||||||
|
case Hexagon::TFR_condset_rr64_f: {
|
||||||
|
int DestReg = MI->getOperand(0).getReg();
|
||||||
|
int SrcReg1 = MI->getOperand(2).getReg();
|
||||||
|
int SrcReg2 = MI->getOperand(3).getReg();
|
||||||
|
|
||||||
int DestReg = MI->getOperand(0).getReg();
|
if (MI->getOpcode() == Hexagon::TFR_condset_rr ||
|
||||||
int SrcReg1 = MI->getOperand(2).getReg();
|
MI->getOpcode() == Hexagon::TFR_condset_rr_f) {
|
||||||
int SrcReg2 = MI->getOperand(3).getReg();
|
Opc1 = Hexagon::TFR_cPt;
|
||||||
|
Opc2 = Hexagon::TFR_cNotPt;
|
||||||
|
}
|
||||||
|
else if (MI->getOpcode() == Hexagon::TFR_condset_rr64_f) {
|
||||||
|
Opc1 = Hexagon::TFR64_cPt;
|
||||||
|
Opc2 = Hexagon::TFR64_cNotPt;
|
||||||
|
}
|
||||||
|
|
||||||
// Minor optimization: do not emit the predicated copy if the source and
|
// Minor optimization: do not emit the predicated copy if the source
|
||||||
// the destination is the same register
|
// and the destination is the same register.
|
||||||
if (DestReg != SrcReg1) {
|
if (DestReg != SrcReg1) {
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cPt),
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc1),
|
||||||
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
|
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
|
||||||
|
}
|
||||||
|
if (DestReg != SrcReg2) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Opc2),
|
||||||
|
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
|
||||||
|
}
|
||||||
|
MII = MBB->erase(MI);
|
||||||
|
--MII;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (DestReg != SrcReg2) {
|
case Hexagon::TFR_condset_ri:
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFR_cNotPt),
|
case Hexagon::TFR_condset_ri_f: {
|
||||||
DestReg).addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
|
int DestReg = MI->getOperand(0).getReg();
|
||||||
|
int SrcReg1 = MI->getOperand(2).getReg();
|
||||||
|
|
||||||
|
// Do not emit the predicated copy if the source and the destination
|
||||||
|
// is the same register.
|
||||||
|
if (DestReg != SrcReg1) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFR_cPt), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).addReg(SrcReg1);
|
||||||
|
}
|
||||||
|
if (MI->getOpcode() == Hexagon::TFR_condset_ri ) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cNotPt), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).
|
||||||
|
addImm(MI->getOperand(3).getImm());
|
||||||
|
} else if (MI->getOpcode() == Hexagon::TFR_condset_ri_f ) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cNotPt_f), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).
|
||||||
|
addFPImm(MI->getOperand(3).getFPImm());
|
||||||
|
}
|
||||||
|
|
||||||
|
MII = MBB->erase(MI);
|
||||||
|
--MII;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Hexagon::TFR_condset_ir:
|
||||||
|
case Hexagon::TFR_condset_ir_f: {
|
||||||
|
int DestReg = MI->getOperand(0).getReg();
|
||||||
|
int SrcReg2 = MI->getOperand(3).getReg();
|
||||||
|
|
||||||
|
if (MI->getOpcode() == Hexagon::TFR_condset_ir ) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cPt), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).
|
||||||
|
addImm(MI->getOperand(2).getImm());
|
||||||
|
} else if (MI->getOpcode() == Hexagon::TFR_condset_ir_f ) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cPt_f), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).
|
||||||
|
addFPImm(MI->getOperand(2).getFPImm());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not emit the predicated copy if the source and
|
||||||
|
// the destination is the same register.
|
||||||
|
if (DestReg != SrcReg2) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFR_cNotPt), DestReg).
|
||||||
|
addReg(MI->getOperand(1).getReg()).addReg(SrcReg2);
|
||||||
|
}
|
||||||
|
MII = MBB->erase(MI);
|
||||||
|
--MII;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Hexagon::TFR_condset_ii:
|
||||||
|
case Hexagon::TFR_condset_ii_f: {
|
||||||
|
int DestReg = MI->getOperand(0).getReg();
|
||||||
|
int SrcReg1 = MI->getOperand(1).getReg();
|
||||||
|
|
||||||
|
if (MI->getOpcode() == Hexagon::TFR_condset_ii ) {
|
||||||
|
int Immed1 = MI->getOperand(2).getImm();
|
||||||
|
int Immed2 = MI->getOperand(3).getImm();
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt),
|
||||||
|
DestReg).addReg(SrcReg1).addImm(Immed1);
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt),
|
||||||
|
DestReg).addReg(SrcReg1).addImm(Immed2);
|
||||||
|
} else if (MI->getOpcode() == Hexagon::TFR_condset_ii_f ) {
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cPt_f), DestReg).
|
||||||
|
addReg(SrcReg1).
|
||||||
|
addFPImm(MI->getOperand(2).getFPImm());
|
||||||
|
BuildMI(*MBB, MII, MI->getDebugLoc(),
|
||||||
|
TII->get(Hexagon::TFRI_cNotPt_f), DestReg).
|
||||||
|
addReg(SrcReg1).
|
||||||
|
addFPImm(MI->getOperand(3).getFPImm());
|
||||||
|
}
|
||||||
|
MII = MBB->erase(MI);
|
||||||
|
--MII;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
MII = MBB->erase(MI);
|
|
||||||
--MII;
|
|
||||||
} else if (Opc == Hexagon::TFR_condset_ii) {
|
|
||||||
int DestReg = MI->getOperand(0).getReg();
|
|
||||||
int SrcReg1 = MI->getOperand(1).getReg();
|
|
||||||
int Immed1 = MI->getOperand(2).getImm();
|
|
||||||
int Immed2 = MI->getOperand(3).getImm();
|
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cPt),
|
|
||||||
DestReg).addReg(SrcReg1).addImm(Immed1);
|
|
||||||
BuildMI(*MBB, MII, MI->getDebugLoc(), TII->get(Hexagon::TFRI_cNotPt),
|
|
||||||
DestReg).addReg(SrcReg1).addImm(Immed2);
|
|
||||||
MII = MBB->erase(MI);
|
|
||||||
--MII;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "HexagonSubtarget.h"
|
#include "HexagonSubtarget.h"
|
||||||
#include "Hexagon.h"
|
#include "Hexagon.h"
|
||||||
|
#include "HexagonRegisterInfo.h"
|
||||||
#include "llvm/Support/CommandLine.h"
|
#include "llvm/Support/CommandLine.h"
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
#include "llvm/Support/ErrorHandling.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
@ -31,6 +32,12 @@ EnableMemOps(
|
|||||||
cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed,
|
cl::Hidden, cl::ZeroOrMore, cl::ValueDisallowed,
|
||||||
cl::desc("Generate V4 MEMOP in code generation for Hexagon target"));
|
cl::desc("Generate V4 MEMOP in code generation for Hexagon target"));
|
||||||
|
|
||||||
|
static cl::opt<bool>
|
||||||
|
EnableIEEERndNear(
|
||||||
|
"enable-hexagon-ieee-rnd-near",
|
||||||
|
cl::Hidden, cl::ZeroOrMore, cl::init(false),
|
||||||
|
cl::desc("Generate non-chopped conversion from fp to int for Hexagon target."));
|
||||||
|
|
||||||
HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
|
HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
|
||||||
HexagonGenSubtargetInfo(TT, CPU, FS),
|
HexagonGenSubtargetInfo(TT, CPU, FS),
|
||||||
HexagonArchVersion(V2),
|
HexagonArchVersion(V2),
|
||||||
@ -45,6 +52,8 @@ HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
|
|||||||
break;
|
break;
|
||||||
case HexagonSubtarget::V4:
|
case HexagonSubtarget::V4:
|
||||||
break;
|
break;
|
||||||
|
case HexagonSubtarget::V5:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
llvm_unreachable("Unknown Architecture Version.");
|
llvm_unreachable("Unknown Architecture Version.");
|
||||||
}
|
}
|
||||||
@ -59,4 +68,10 @@ HexagonSubtarget::HexagonSubtarget(StringRef TT, StringRef CPU, StringRef FS):
|
|||||||
UseMemOps = true;
|
UseMemOps = true;
|
||||||
else
|
else
|
||||||
UseMemOps = false;
|
UseMemOps = false;
|
||||||
|
|
||||||
|
if (EnableIEEERndNear)
|
||||||
|
ModeIEEERndNear = true;
|
||||||
|
else
|
||||||
|
ModeIEEERndNear = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,16 +22,18 @@
|
|||||||
#include "HexagonGenSubtargetInfo.inc"
|
#include "HexagonGenSubtargetInfo.inc"
|
||||||
|
|
||||||
#define Hexagon_SMALL_DATA_THRESHOLD 8
|
#define Hexagon_SMALL_DATA_THRESHOLD 8
|
||||||
|
#define Hexagon_SLOTS 4
|
||||||
|
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
|
|
||||||
class HexagonSubtarget : public HexagonGenSubtargetInfo {
|
class HexagonSubtarget : public HexagonGenSubtargetInfo {
|
||||||
|
|
||||||
bool UseMemOps;
|
bool UseMemOps;
|
||||||
|
bool ModeIEEERndNear;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum HexagonArchEnum {
|
enum HexagonArchEnum {
|
||||||
V1, V2, V3, V4
|
V1, V2, V3, V4, V5
|
||||||
};
|
};
|
||||||
|
|
||||||
HexagonArchEnum HexagonArchVersion;
|
HexagonArchEnum HexagonArchVersion;
|
||||||
@ -55,7 +57,11 @@ public:
|
|||||||
bool hasV3TOps () const { return HexagonArchVersion >= V3; }
|
bool hasV3TOps () const { return HexagonArchVersion >= V3; }
|
||||||
bool hasV3TOpsOnly () const { return HexagonArchVersion == V3; }
|
bool hasV3TOpsOnly () const { return HexagonArchVersion == V3; }
|
||||||
bool hasV4TOps () const { return HexagonArchVersion >= V4; }
|
bool hasV4TOps () const { return HexagonArchVersion >= V4; }
|
||||||
|
bool hasV4TOpsOnly () const { return HexagonArchVersion == V4; }
|
||||||
bool useMemOps () const { return HexagonArchVersion >= V4 && UseMemOps; }
|
bool useMemOps () const { return HexagonArchVersion >= V4 && UseMemOps; }
|
||||||
|
bool hasV5TOps () const { return HexagonArchVersion >= V5; }
|
||||||
|
bool hasV5TOpsOnly () const { return HexagonArchVersion == V5; }
|
||||||
|
bool modeIEEERndNear () const { return ModeIEEERndNear; }
|
||||||
|
|
||||||
bool isSubtargetV2() const { return HexagonArchVersion == V2;}
|
bool isSubtargetV2() const { return HexagonArchVersion == V2;}
|
||||||
const std::string &getCPUString () const { return CPUString; }
|
const std::string &getCPUString () const { return CPUString; }
|
||||||
|
@ -55,7 +55,9 @@ HexagonTargetMachine::HexagonTargetMachine(const Target &T, StringRef TT,
|
|||||||
CodeModel::Model CM,
|
CodeModel::Model CM,
|
||||||
CodeGenOpt::Level OL)
|
CodeGenOpt::Level OL)
|
||||||
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
|
||||||
DataLayout("e-p:32:32:32-i64:64:64-i32:32:32-i16:16:16-i1:32:32-a0:0") ,
|
DataLayout("e-p:32:32:32-"
|
||||||
|
"i64:64:64-i32:32:32-i16:16:16-i1:32:32-"
|
||||||
|
"f64:64:64-f32:32:32-a0:0-n32") ,
|
||||||
Subtarget(TT, CPU, FS), InstrInfo(Subtarget), TLInfo(*this),
|
Subtarget(TT, CPU, FS), InstrInfo(Subtarget), TLInfo(*this),
|
||||||
TSInfo(*this),
|
TSInfo(*this),
|
||||||
FrameLowering(Subtarget),
|
FrameLowering(Subtarget),
|
||||||
|
26
test/CodeGen/Hexagon/convertdptoint.ll
Normal file
26
test/CodeGen/Hexagon/convertdptoint.ll
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from double precision floating point
|
||||||
|
; to 32-bit int value in IEEE complaint mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_df2w(r{{[0-9]+}}:{{[0-9]+}}):chop
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i32, align 4
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %a, align 8
|
||||||
|
%1 = load double* %b, align 8
|
||||||
|
%add = fadd double %0, %1
|
||||||
|
store double %add, double* %c, align 8
|
||||||
|
%2 = load double* %c, align 8
|
||||||
|
%conv = fptosi double %2 to i32
|
||||||
|
store i32 %conv, i32* %i, align 4
|
||||||
|
%3 = load i32* %i, align 4
|
||||||
|
ret i32 %3
|
||||||
|
}
|
27
test/CodeGen/Hexagon/convertdptoll.ll
Normal file
27
test/CodeGen/Hexagon/convertdptoll.ll
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from double precision floating point
|
||||||
|
; to 64-bit integer value in IEEE complaint mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_df2d(r{{[0-9]+}}:{{[0-9]+}}):chop
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i64, align 8
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %a, align 8
|
||||||
|
%1 = load double* %b, align 8
|
||||||
|
%add = fadd double %0, %1
|
||||||
|
store double %add, double* %c, align 8
|
||||||
|
%2 = load double* %c, align 8
|
||||||
|
%conv = fptosi double %2 to i64
|
||||||
|
store i64 %conv, i64* %i, align 8
|
||||||
|
%3 = load i64* %i, align 8
|
||||||
|
%conv1 = trunc i64 %3 to i32
|
||||||
|
ret i32 %conv1
|
||||||
|
}
|
26
test/CodeGen/Hexagon/convertsptoint.ll
Normal file
26
test/CodeGen/Hexagon/convertsptoint.ll
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from single precision floating point
|
||||||
|
; to 32-bit int value in IEEE complaint mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_sf2w(r{{[0-9]+}}):chop
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i32, align 4
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %a, align 4
|
||||||
|
%1 = load float* %b, align 4
|
||||||
|
%add = fadd float %0, %1
|
||||||
|
store float %add, float* %c, align 4
|
||||||
|
%2 = load float* %c, align 4
|
||||||
|
%conv = fptosi float %2 to i32
|
||||||
|
store i32 %conv, i32* %i, align 4
|
||||||
|
%3 = load i32* %i, align 4
|
||||||
|
ret i32 %3
|
||||||
|
}
|
27
test/CodeGen/Hexagon/convertsptoll.ll
Normal file
27
test/CodeGen/Hexagon/convertsptoll.ll
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from single precision floating point
|
||||||
|
; to 64-bit int value in IEEE complaint mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_sf2d(r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i64, align 8
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %a, align 4
|
||||||
|
%1 = load float* %b, align 4
|
||||||
|
%add = fadd float %0, %1
|
||||||
|
store float %add, float* %c, align 4
|
||||||
|
%2 = load float* %c, align 4
|
||||||
|
%conv = fptosi float %2 to i64
|
||||||
|
store i64 %conv, i64* %i, align 8
|
||||||
|
%3 = load i64* %i, align 8
|
||||||
|
%conv1 = trunc i64 %3 to i32
|
||||||
|
ret i32 %conv1
|
||||||
|
}
|
19
test/CodeGen/Hexagon/dadd.ll
Normal file
19
test/CodeGen/Hexagon/dadd.ll
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate double precision floating point add in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = dfadd(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %a, align 8
|
||||||
|
%1 = load double* %b, align 8
|
||||||
|
%add = fadd double %0, %1
|
||||||
|
store double %add, double* %c, align 8
|
||||||
|
ret i32 0
|
||||||
|
}
|
18
test/CodeGen/Hexagon/dmul.ll
Normal file
18
test/CodeGen/Hexagon/dmul.ll
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate double precision floating point multiply in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}}:{{[0-9]+}} = dfmpy(r{{[0-9]+}}:{{[0-9]+}}, r{{[0-9]+}}:{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %b, align 8
|
||||||
|
%1 = load double* %a, align 8
|
||||||
|
%mul = fmul double %0, %1
|
||||||
|
store double %mul, double* %c, align 8
|
||||||
|
ret i32 0
|
||||||
|
}
|
26
test/CodeGen/Hexagon/doubleconvert-ieee-rnd-near.ll
Normal file
26
test/CodeGen/Hexagon/doubleconvert-ieee-rnd-near.ll
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 -enable-hexagon-ieee-rnd-near < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from double precision floating point
|
||||||
|
; to 32-bit int value in IEEE rounding to the nearest mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_df2w(r{{[0-9]+}}:{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i32, align 4
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %a, align 8
|
||||||
|
%1 = load double* %b, align 8
|
||||||
|
%add = fadd double %0, %1
|
||||||
|
store double %add, double* %c, align 8
|
||||||
|
%2 = load double* %c, align 8
|
||||||
|
%conv = fptosi double %2 to i32
|
||||||
|
store i32 %conv, i32* %i, align 4
|
||||||
|
%3 = load i32* %i, align 4
|
||||||
|
ret i32 %3
|
||||||
|
}
|
18
test/CodeGen/Hexagon/dsub.ll
Normal file
18
test/CodeGen/Hexagon/dsub.ll
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate double precision floating point subtract in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = dfsub(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca double, align 8
|
||||||
|
%b = alloca double, align 8
|
||||||
|
%c = alloca double, align 8
|
||||||
|
store double 1.540000e+01, double* %a, align 8
|
||||||
|
store double 9.100000e+00, double* %b, align 8
|
||||||
|
%0 = load double* %b, align 8
|
||||||
|
%1 = load double* %a, align 8
|
||||||
|
%sub = fsub double %0, %1
|
||||||
|
store double %sub, double* %c, align 8
|
||||||
|
ret i32 0
|
||||||
|
}
|
18
test/CodeGen/Hexagon/fadd.ll
Normal file
18
test/CodeGen/Hexagon/fadd.ll
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate sp floating point add in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = sfadd(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %a, align 4
|
||||||
|
%1 = load float* %b, align 4
|
||||||
|
%add = fadd float %0, %1
|
||||||
|
store float %add, float* %c, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
37
test/CodeGen/Hexagon/fcmp.ll
Normal file
37
test/CodeGen/Hexagon/fcmp.ll
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate floating point compare in V5
|
||||||
|
|
||||||
|
; CHECK: p{{[0-2]+}} = sfcmp.{{.}}
|
||||||
|
|
||||||
|
define i32 @foo(float %y) nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%y.addr = alloca float, align 4
|
||||||
|
store float %y, float* %y.addr, align 4
|
||||||
|
%0 = load float* %y.addr, align 4
|
||||||
|
%cmp = fcmp ogt float %0, 0x406AD7EFA0000000
|
||||||
|
br i1 %cmp, label %if.then, label %if.else
|
||||||
|
|
||||||
|
if.then: ; preds = %entry
|
||||||
|
store i32 1, i32* %retval
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
if.else: ; preds = %entry
|
||||||
|
store i32 2, i32* %retval
|
||||||
|
br label %return
|
||||||
|
|
||||||
|
return: ; preds = %if.else, %if.then
|
||||||
|
%1 = load i32* %retval
|
||||||
|
ret i32 %1
|
||||||
|
}
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%a = alloca float, align 4
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store float 0x40012E0A00000000, float* %a, align 4
|
||||||
|
%0 = load float* %a, align 4
|
||||||
|
%call = call i32 @foo(float %0)
|
||||||
|
ret i32 %call
|
||||||
|
}
|
26
test/CodeGen/Hexagon/floatconvert-ieee-rnd-near.ll
Normal file
26
test/CodeGen/Hexagon/floatconvert-ieee-rnd-near.ll
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate conversion from double precision floating point
|
||||||
|
; to 32-bit int value in IEEE rounding to the nearest mode in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = convert_sf2w(r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%retval = alloca i32, align 4
|
||||||
|
%i = alloca i32, align 4
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store i32 0, i32* %retval
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %a, align 4
|
||||||
|
%1 = load float* %b, align 4
|
||||||
|
%add = fadd float %0, %1
|
||||||
|
store float %add, float* %c, align 4
|
||||||
|
%2 = load float* %c, align 4
|
||||||
|
%conv = fptosi float %2 to i32
|
||||||
|
store i32 %conv, i32* %i, align 4
|
||||||
|
%3 = load i32* %i, align 4
|
||||||
|
ret i32 %3
|
||||||
|
}
|
19
test/CodeGen/Hexagon/fmul.ll
Normal file
19
test/CodeGen/Hexagon/fmul.ll
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate single precision floating point multiply in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = sfmpy(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %b, align 4
|
||||||
|
%1 = load float* %a, align 4
|
||||||
|
%mul = fmul float %0, %1
|
||||||
|
store float %mul, float* %c, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
18
test/CodeGen/Hexagon/fsub.ll
Normal file
18
test/CodeGen/Hexagon/fsub.ll
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate sp floating point subtract in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = sfsub(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main() nounwind {
|
||||||
|
entry:
|
||||||
|
%a = alloca float, align 4
|
||||||
|
%b = alloca float, align 4
|
||||||
|
%c = alloca float, align 4
|
||||||
|
store float 0x402ECCCCC0000000, float* %a, align 4
|
||||||
|
store float 0x4022333340000000, float* %b, align 4
|
||||||
|
%0 = load float* %b, align 4
|
||||||
|
%1 = load float* %a, align 4
|
||||||
|
%sub = fsub float %0, %1
|
||||||
|
store float %sub, float* %c, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
14
test/CodeGen/Hexagon/macint.ll
Normal file
14
test/CodeGen/Hexagon/macint.ll
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Check that we generate integer multiply accumulate.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} += mpyi(r{{[0-9]+}}, r{{[0-9]+}})
|
||||||
|
|
||||||
|
define i32 @main(i32* %a, i32* %b) nounwind {
|
||||||
|
entry:
|
||||||
|
%0 = load i32* %a, align 4
|
||||||
|
%div = udiv i32 %0, 10000
|
||||||
|
%rem = urem i32 %div, 10
|
||||||
|
store i32 %rem, i32* %b, align 4
|
||||||
|
ret i32 0
|
||||||
|
}
|
||||||
|
|
15
test/CodeGen/Hexagon/opt-fabs.ll
Normal file
15
test/CodeGen/Hexagon/opt-fabs.ll
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Optimize fabsf to clrbit in V5.
|
||||||
|
|
||||||
|
; CHECK: r{{[0-9]+}} = clrbit(r{{[0-9]+}}, #31)
|
||||||
|
|
||||||
|
define float @my_fabsf(float %x) nounwind {
|
||||||
|
entry:
|
||||||
|
%x.addr = alloca float, align 4
|
||||||
|
store float %x, float* %x.addr, align 4
|
||||||
|
%0 = load float* %x.addr, align 4
|
||||||
|
%call = call float @fabsf(float %0)
|
||||||
|
ret float %call
|
||||||
|
}
|
||||||
|
|
||||||
|
declare float @fabsf(float)
|
24
test/CodeGen/Hexagon/opt-fneg.ll
Normal file
24
test/CodeGen/Hexagon/opt-fneg.ll
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
|
||||||
|
; Optimize fneg to togglebit in V5.
|
||||||
|
|
||||||
|
define float @bar(float %x) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: r{{[0-9]+}} = togglebit(r{{[0-9]+}}, #31)
|
||||||
|
%x.addr = alloca float, align 4
|
||||||
|
store float %x, float* %x.addr, align 4
|
||||||
|
%0 = load float* %x.addr, align 4
|
||||||
|
%sub = fsub float -0.000000e+00, %0
|
||||||
|
ret float %sub
|
||||||
|
}
|
||||||
|
|
||||||
|
define float @baz(float %x) nounwind {
|
||||||
|
entry:
|
||||||
|
; CHECK: r{{[0-9]+}} = togglebit(r{{[0-9]+}}, #31)
|
||||||
|
%x.addr = alloca float, align 4
|
||||||
|
store float %x, float* %x.addr, align 4
|
||||||
|
%0 = load float* %x.addr, align 4
|
||||||
|
%conv = fpext float %0 to double
|
||||||
|
%mul = fmul double %conv, -1.000000e+00
|
||||||
|
%conv1 = fptrunc double %mul to float
|
||||||
|
ret float %conv1
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user