From: Krzysztof Parzyszek Date: Sun, 6 Nov 2016 19:03:38 +0000 (+0000) Subject: [Hexagon] Remove redundant custom selection code X-Git-Tag: llvmorg-4.0.0-rc1~5386 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9e3520c884b1a29ed3e5d10211f63f8d377db15b;p=platform%2Fupstream%2Fllvm.git [Hexagon] Remove redundant custom selection code The clr/set/toggle-bit instructions (with the bit index given as an immediate operand) had both, custom selection code that generated them, and selection patterns at the same time. The selection patterns were not used, because the custom selection code was executed first. This patch removes the custom code in favor of the selection patterns. The custom code handled 64-bit registers as well with an immediate bit index, and so new patterns were added to implement that. It was also the same case for the instruction "Rd += asr(Rs, Rt)", except that the custom code did not offer any additional functionality, and was simply removed. llvm-svn: 286080 --- diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 8ffa369..e5e2c8b 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/llvm/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/llvm/lib/Target/Hexagon/HexagonPatterns.td b/llvm/lib/Target/Hexagon/HexagonPatterns.td index bce46ef..f46a558 100644 --- a/llvm/lib/Target/Hexagon/HexagonPatterns.td +++ b/llvm/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);