mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-27 21:50:40 +00:00
Reapply r286080 with a phony change in Hexagon's CMakeLists.txt
Cmake has not recognized that Hexagon.td has a new dependency in HexagonPatterns.td. All changes to that file were not visible to the build bots. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286084 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ef6860ffdf
commit
b63144f892
@ -64,3 +64,4 @@ add_subdirectory(AsmParser)
|
||||
add_subdirectory(TargetInfo)
|
||||
add_subdirectory(MCTargetDesc)
|
||||
add_subdirectory(Disassembler)
|
||||
|
||||
|
@ -112,9 +112,7 @@ public:
|
||||
void SelectIntrinsicWOChain(SDNode *N);
|
||||
void SelectConstant(SDNode *N);
|
||||
void SelectConstantFP(SDNode *N);
|
||||
void SelectAdd(SDNode *N);
|
||||
void SelectBitcast(SDNode *N);
|
||||
void SelectBitOp(SDNode *N);
|
||||
|
||||
// Include the pieces autogenerated from the target description.
|
||||
#include "HexagonGenDAGISel.inc"
|
||||
@ -888,180 +886,6 @@ void HexagonDAGToDAGISel::SelectConstant(SDNode *N) {
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Map add followed by a asr -> asr +=.
|
||||
//
|
||||
void HexagonDAGToDAGISel::SelectAdd(SDNode *N) {
|
||||
SDLoc dl(N);
|
||||
if (N->getValueType(0) != MVT::i32) {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
// Identify nodes of the form: add(asr(...)).
|
||||
SDNode* Src1 = N->getOperand(0).getNode();
|
||||
if (Src1->getOpcode() != ISD::SRA || !Src1->hasOneUse() ||
|
||||
Src1->getValueType(0) != MVT::i32) {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
|
||||
// Build Rd = Rd' + asr(Rs, Rt). The machine constraints will ensure that
|
||||
// Rd and Rd' are assigned to the same register
|
||||
SDNode* Result = CurDAG->getMachineNode(Hexagon::S2_asr_r_r_acc, dl, MVT::i32,
|
||||
N->getOperand(1),
|
||||
Src1->getOperand(0),
|
||||
Src1->getOperand(1));
|
||||
ReplaceNode(N, Result);
|
||||
}
|
||||
|
||||
//
|
||||
// Map the following, where possible.
|
||||
// AND/FABS -> clrbit
|
||||
// OR -> setbit
|
||||
// XOR/FNEG ->toggle_bit.
|
||||
//
|
||||
void HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
SDLoc dl(N);
|
||||
EVT ValueVT = N->getValueType(0);
|
||||
|
||||
// We handle only 32 and 64-bit bit ops.
|
||||
if (!(ValueVT == MVT::i32 || ValueVT == MVT::i64 ||
|
||||
ValueVT == MVT::f32 || ValueVT == MVT::f64)) {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
|
||||
// We handly only fabs and fneg for V5.
|
||||
unsigned Opc = N->getOpcode();
|
||||
if ((Opc == ISD::FABS || Opc == ISD::FNEG) && !HST->hasV5TOps()) {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t Val = 0;
|
||||
if (Opc != ISD::FABS && Opc != ISD::FNEG) {
|
||||
if (N->getOperand(1).getOpcode() == ISD::Constant)
|
||||
Val = cast<ConstantSDNode>((N)->getOperand(1))->getSExtValue();
|
||||
else {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (Opc == ISD::AND) {
|
||||
// Check if this is a bit-clearing AND, if not select code the usual way.
|
||||
if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
|
||||
(ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
|
||||
Val = ~Val;
|
||||
else {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If OR or AND is being fed by shl, srl and, sra don't do this change,
|
||||
// because Hexagon provide |= &= on shl, srl, and sra.
|
||||
// Traverse the DAG to see if there is shl, srl and sra.
|
||||
if (Opc == ISD::OR || Opc == ISD::AND) {
|
||||
switch (N->getOperand(0)->getOpcode()) {
|
||||
default:
|
||||
break;
|
||||
case ISD::SRA:
|
||||
case ISD::SRL:
|
||||
case ISD::SHL:
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure it's power of 2.
|
||||
unsigned BitPos = 0;
|
||||
if (Opc != ISD::FABS && Opc != ISD::FNEG) {
|
||||
if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
|
||||
(ValueVT == MVT::i64 && !isPowerOf2_64(Val))) {
|
||||
SelectCode(N);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the bit position.
|
||||
BitPos = countTrailingZeros(uint64_t(Val));
|
||||
} else {
|
||||
// For fabs and fneg, it's always the 31st bit.
|
||||
BitPos = 31;
|
||||
}
|
||||
|
||||
unsigned BitOpc = 0;
|
||||
// Set the right opcode for bitwise operations.
|
||||
switch (Opc) {
|
||||
default:
|
||||
llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
|
||||
case ISD::AND:
|
||||
case ISD::FABS:
|
||||
BitOpc = Hexagon::S2_clrbit_i;
|
||||
break;
|
||||
case ISD::OR:
|
||||
BitOpc = Hexagon::S2_setbit_i;
|
||||
break;
|
||||
case ISD::XOR:
|
||||
case ISD::FNEG:
|
||||
BitOpc = Hexagon::S2_togglebit_i;
|
||||
break;
|
||||
}
|
||||
|
||||
SDNode *Result;
|
||||
// Get the right SDVal for the opcode.
|
||||
SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
|
||||
|
||||
if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
|
||||
Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
|
||||
N->getOperand(0), SDVal);
|
||||
} else {
|
||||
// 64-bit gymnastic to use REG_SEQUENCE. But it's worth it.
|
||||
EVT SubValueVT;
|
||||
if (ValueVT == MVT::i64)
|
||||
SubValueVT = MVT::i32;
|
||||
else
|
||||
SubValueVT = MVT::f32;
|
||||
|
||||
SDNode *Reg = N->getOperand(0).getNode();
|
||||
SDValue RegClass = CurDAG->getTargetConstant(Hexagon::DoubleRegsRegClassID,
|
||||
dl, MVT::i64);
|
||||
|
||||
SDValue SubregHiIdx = CurDAG->getTargetConstant(Hexagon::subreg_hireg, dl,
|
||||
MVT::i32);
|
||||
SDValue SubregLoIdx = CurDAG->getTargetConstant(Hexagon::subreg_loreg, dl,
|
||||
MVT::i32);
|
||||
|
||||
SDValue SubregHI = CurDAG->getTargetExtractSubreg(Hexagon::subreg_hireg, dl,
|
||||
MVT::i32, SDValue(Reg, 0));
|
||||
|
||||
SDValue SubregLO = CurDAG->getTargetExtractSubreg(Hexagon::subreg_loreg, dl,
|
||||
MVT::i32, SDValue(Reg, 0));
|
||||
|
||||
// Clear/set/toggle hi or lo registers depending on the bit position.
|
||||
if (SubValueVT != MVT::f32 && BitPos < 32) {
|
||||
SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
|
||||
SubregLO, SDVal);
|
||||
const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
|
||||
SDValue(Result0, 0), SubregLoIdx };
|
||||
Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
|
||||
dl, ValueVT, Ops);
|
||||
} else {
|
||||
if (Opc != ISD::FABS && Opc != ISD::FNEG)
|
||||
SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
|
||||
SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
|
||||
SubregHI, SDVal);
|
||||
const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
|
||||
SubregLO, SubregLoIdx };
|
||||
Result = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE,
|
||||
dl, ValueVT, Ops);
|
||||
}
|
||||
}
|
||||
|
||||
ReplaceNode(N, Result);
|
||||
}
|
||||
|
||||
|
||||
void HexagonDAGToDAGISel::SelectFrameIndex(SDNode *N) {
|
||||
MachineFrameInfo &MFI = MF->getFrameInfo();
|
||||
const HexagonFrameLowering *HFI = HST->getFrameLowering();
|
||||
@ -1127,10 +951,6 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
|
||||
SelectFrameIndex(N);
|
||||
return;
|
||||
|
||||
case ISD::ADD:
|
||||
SelectAdd(N);
|
||||
return;
|
||||
|
||||
case ISD::BITCAST:
|
||||
SelectBitcast(N);
|
||||
return;
|
||||
@ -1151,14 +971,6 @@ void HexagonDAGToDAGISel::Select(SDNode *N) {
|
||||
SelectMul(N);
|
||||
return;
|
||||
|
||||
case ISD::AND:
|
||||
case ISD::OR:
|
||||
case ISD::XOR:
|
||||
case ISD::FABS:
|
||||
case ISD::FNEG:
|
||||
SelectBitOp(N);
|
||||
return;
|
||||
|
||||
case ISD::ZERO_EXTEND:
|
||||
SelectZeroExtend(N);
|
||||
return;
|
||||
|
@ -24,9 +24,34 @@ def IsPow2_32 : PatLeaf<(i32 imm), [{
|
||||
return isPowerOf2_32(V);
|
||||
}]>;
|
||||
|
||||
def IsPow2_64 : PatLeaf<(i64 imm), [{
|
||||
uint64_t V = N->getZExtValue();
|
||||
return isPowerOf2_64(V);
|
||||
}]>;
|
||||
|
||||
def IsNPow2_32 : PatLeaf<(i32 imm), [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
return isPowerOf2_32(~V);
|
||||
uint32_t NV = ~N->getZExtValue();
|
||||
return isPowerOf2_32(NV);
|
||||
}]>;
|
||||
|
||||
def IsPow2_64L : PatLeaf<(i64 imm), [{
|
||||
uint64_t V = N->getZExtValue();
|
||||
return isPowerOf2_64(V) && Log2_64(V) < 32;
|
||||
}]>;
|
||||
|
||||
def IsPow2_64H : PatLeaf<(i64 imm), [{
|
||||
uint64_t V = N->getZExtValue();
|
||||
return isPowerOf2_64(V) && Log2_64(V) >= 32;
|
||||
}]>;
|
||||
|
||||
def IsNPow2_64L : PatLeaf<(i64 imm), [{
|
||||
uint64_t NV = ~N->getZExtValue();
|
||||
return isPowerOf2_64(NV) && Log2_64(NV) < 32;
|
||||
}]>;
|
||||
|
||||
def IsNPow2_64H : PatLeaf<(i64 imm), [{
|
||||
uint64_t NV = ~N->getZExtValue();
|
||||
return isPowerOf2_64(NV) && Log2_64(NV) >= 32;
|
||||
}]>;
|
||||
|
||||
def SDEC1 : SDNodeXForm<imm, [{
|
||||
@ -36,15 +61,36 @@ def SDEC1 : SDNodeXForm<imm, [{
|
||||
|
||||
def UDEC1 : SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(V > 0);
|
||||
assert(V >= 1);
|
||||
return CurDAG->getTargetConstant(V-1, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def UDEC32 : SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
assert(V >= 32);
|
||||
return CurDAG->getTargetConstant(V-32, SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def Log2_32 : SDNodeXForm<imm, [{
|
||||
uint32_t V = N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(Log2_32(V), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def Log2_64 : SDNodeXForm<imm, [{
|
||||
uint64_t V = N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(Log2_64(V), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def LogN2_32 : SDNodeXForm<imm, [{
|
||||
uint32_t NV = ~N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def LogN2_64 : SDNodeXForm<imm, [{
|
||||
uint64_t NV = ~N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(Log2_64(NV), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
|
||||
class T_CMP_pat <InstHexagon MI, PatFrag OpNode, PatLeaf ImmPred>
|
||||
: Pat<(i1 (OpNode I32:$src1, ImmPred:$src2)),
|
||||
@ -528,18 +574,54 @@ def: Pat<(i32 (trunc (ctlz (not I64:$Rss)))), (S2_cl1p I64:$Rss)>;
|
||||
// Count trailing ones: 32-bit.
|
||||
def: Pat<(cttz (not I32:$Rs)), (S2_ct1 I32:$Rs)>;
|
||||
|
||||
def: Pat<(i32 (and I32:$Rs, (not (shl 1, u5_0ImmPred:$u5)))),
|
||||
(S2_clrbit_i IntRegs:$Rs, u5_0ImmPred:$u5)>;
|
||||
def: Pat<(i32 (or I32:$Rs, (shl 1, u5_0ImmPred:$u5))),
|
||||
(S2_setbit_i IntRegs:$Rs, u5_0ImmPred:$u5)>;
|
||||
def: Pat<(i32 (xor I32:$Rs, (shl 1, u5_0ImmPred:$u5))),
|
||||
(S2_togglebit_i IntRegs:$Rs, u5_0ImmPred:$u5)>;
|
||||
def: Pat<(i32 (and I32:$Rs, (not (shl 1, I32:$Rt)))),
|
||||
(S2_clrbit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
def: Pat<(i32 (or I32:$Rs, (shl 1, I32:$Rt))),
|
||||
(S2_setbit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
def: Pat<(i32 (xor I32:$Rs, (shl 1, I32:$Rt))),
|
||||
(S2_togglebit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
let AddedComplexity = 20 in { // Complexity greater than and/or/xor
|
||||
def: Pat<(and I32:$Rs, IsNPow2_32:$V),
|
||||
(S2_clrbit_i IntRegs:$Rs, (LogN2_32 $V))>;
|
||||
def: Pat<(or I32:$Rs, IsPow2_32:$V),
|
||||
(S2_setbit_i IntRegs:$Rs, (Log2_32 $V))>;
|
||||
def: Pat<(xor I32:$Rs, IsPow2_32:$V),
|
||||
(S2_togglebit_i IntRegs:$Rs, (Log2_32 $V))>;
|
||||
|
||||
def: Pat<(and I32:$Rs, (not (shl 1, I32:$Rt))),
|
||||
(S2_clrbit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
def: Pat<(or I32:$Rs, (shl 1, I32:$Rt)),
|
||||
(S2_setbit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
def: Pat<(xor I32:$Rs, (shl 1, I32:$Rt)),
|
||||
(S2_togglebit_r IntRegs:$Rs, IntRegs:$Rt)>;
|
||||
}
|
||||
|
||||
// Clr/set/toggle bit for 64-bit values with immediate bit index.
|
||||
let AddedComplexity = 20 in { // Complexity greater than and/or/xor
|
||||
def: Pat<(and I64:$Rss, IsNPow2_64L:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(i32 (HiReg $Rss)), subreg_hireg,
|
||||
(S2_clrbit_i (LoReg $Rss), (LogN2_64 $V)), subreg_loreg)>;
|
||||
def: Pat<(and I64:$Rss, IsNPow2_64H:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(S2_clrbit_i (HiReg $Rss), (UDEC32 (i32 (LogN2_64 $V)))),
|
||||
subreg_hireg,
|
||||
(i32 (LoReg $Rss)), subreg_loreg)>;
|
||||
|
||||
def: Pat<(or I64:$Rss, IsPow2_64L:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(i32 (HiReg $Rss)), subreg_hireg,
|
||||
(S2_setbit_i (LoReg $Rss), (Log2_64 $V)), subreg_loreg)>;
|
||||
def: Pat<(or I64:$Rss, IsPow2_64H:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(S2_setbit_i (HiReg $Rss), (UDEC32 (i32 (Log2_64 $V)))),
|
||||
subreg_hireg,
|
||||
(i32 (LoReg $Rss)), subreg_loreg)>;
|
||||
|
||||
def: Pat<(xor I64:$Rss, IsPow2_64L:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(i32 (HiReg $Rss)), subreg_hireg,
|
||||
(S2_togglebit_i (LoReg $Rss), (Log2_64 $V)), subreg_loreg)>;
|
||||
def: Pat<(xor I64:$Rss, IsPow2_64H:$V),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(S2_togglebit_i (HiReg $Rss), (UDEC32 (i32 (Log2_64 $V)))),
|
||||
subreg_hireg,
|
||||
(i32 (LoReg $Rss)), subreg_loreg)>;
|
||||
}
|
||||
|
||||
let AddedComplexity = 20 in { // Complexity greater than cmp reg-imm.
|
||||
def: Pat<(i1 (setne (and (shl 1, u5_0ImmPred:$u5), I32:$Rs), 0)),
|
||||
@ -1642,11 +1724,6 @@ def LogN2_16 : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def LogN2_32 : SDNodeXForm<imm, [{
|
||||
uint32_t NV = ~N->getZExtValue();
|
||||
return CurDAG->getTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def NegImm8 : SDNodeXForm<imm, [{
|
||||
int8_t NV = -N->getSExtValue();
|
||||
return CurDAG->getTargetConstant(NV, SDLoc(N), MVT::i32);
|
||||
@ -2615,6 +2692,15 @@ def : Pat <(fneg F32:$src1),
|
||||
(S2_togglebit_i F32:$src1, 31)>,
|
||||
Requires<[HasV5T]>;
|
||||
|
||||
def: Pat<(fabs F64:$Rs),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(S2_clrbit_i (HiReg $Rs), 31), subreg_hireg,
|
||||
(i32 (LoReg $Rs)), subreg_loreg)>;
|
||||
|
||||
def: Pat<(fneg F64:$Rs),
|
||||
(REG_SEQUENCE DoubleRegs,
|
||||
(S2_togglebit_i (HiReg $Rs), 31), subreg_hireg,
|
||||
(i32 (LoReg $Rs)), subreg_loreg)>;
|
||||
|
||||
def alignedload : PatFrag<(ops node:$addr), (load $addr), [{
|
||||
return isAlignedMemNode(dyn_cast<MemSDNode>(N));
|
||||
|
Loading…
Reference in New Issue
Block a user