From b63144f8926661bf3d2b3f34f2225e97f044446d Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Sun, 6 Nov 2016 20:55:57 +0000 Subject: [PATCH] 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 --- lib/Target/Hexagon/CMakeLists.txt | 1 + lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 188 --------------------- lib/Target/Hexagon/HexagonPatterns.td | 126 +++++++++++--- 3 files changed, 107 insertions(+), 208 deletions(-) diff --git a/lib/Target/Hexagon/CMakeLists.txt b/lib/Target/Hexagon/CMakeLists.txt index 759a75b6aa5..2c527d59862 100644 --- a/lib/Target/Hexagon/CMakeLists.txt +++ b/lib/Target/Hexagon/CMakeLists.txt @@ -64,3 +64,4 @@ add_subdirectory(AsmParser) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) add_subdirectory(Disassembler) + diff --git a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 8ffa3691d59..e5e2c8bd6b0 100644 --- a/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -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((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; diff --git a/lib/Target/Hexagon/HexagonPatterns.td b/lib/Target/Hexagon/HexagonPatterns.td index bce46efb018..71cb5224dad 100644 --- a/lib/Target/Hexagon/HexagonPatterns.td +++ b/lib/Target/Hexagon/HexagonPatterns.td @@ -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 : SDNodeXFormgetZExtValue(); - assert(V > 0); + assert(V >= 1); return CurDAG->getTargetConstant(V-1, SDLoc(N), MVT::i32); }]>; +def UDEC32 : SDNodeXFormgetZExtValue(); + assert(V >= 32); + return CurDAG->getTargetConstant(V-32, SDLoc(N), MVT::i32); +}]>; + def Log2_32 : SDNodeXFormgetZExtValue(); return CurDAG->getTargetConstant(Log2_32(V), SDLoc(N), MVT::i32); }]>; +def Log2_64 : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(Log2_64(V), SDLoc(N), MVT::i32); +}]>; + +def LogN2_32 : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32); +}]>; + +def LogN2_64 : SDNodeXFormgetZExtValue(); + return CurDAG->getTargetConstant(Log2_64(NV), SDLoc(N), MVT::i32); +}]>; + class T_CMP_pat : 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 : SDNodeXFormgetTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32); }]>; -def LogN2_32 : SDNodeXFormgetZExtValue(); - return CurDAG->getTargetConstant(Log2_32(NV), SDLoc(N), MVT::i32); -}]>; - def NegImm8 : SDNodeXFormgetSExtValue(); 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(N));