[llvm] r286080 - [Hexagon] Remove redundant custom selection code
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Sun Nov 6 11:03:38 PST 2016
Author: kparzysz
Date: Sun Nov 6 13:03:38 2016
New Revision: 286080
URL: http://llvm.org/viewvc/llvm-project?rev=286080&view=rev
Log:
[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.
Modified:
llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
Modified: llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp?rev=286080&r1=286079&r2=286080&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp Sun Nov 6 13:03:38 2016
@@ -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
}
-//
-// 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
SelectFrameIndex(N);
return;
- case ISD::ADD:
- SelectAdd(N);
- return;
-
case ISD::BITCAST:
SelectBitcast(N);
return;
@@ -1151,14 +971,6 @@ void HexagonDAGToDAGISel::Select(SDNode
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;
Modified: llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td?rev=286080&r1=286079&r2=286080&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td (original)
+++ llvm/trunk/lib/Target/Hexagon/HexagonPatterns.td Sun Nov 6 13:03:38 2016
@@ -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
// 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);
More information about the llvm-commits
mailing list