aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeDAG.cpp16
-rw-r--r--lib/Target/PowerPC/PPCISelPattern.cpp34
2 files changed, 41 insertions, 9 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
index a511202a53..08e8d776fd 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
@@ -1156,15 +1156,25 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
break;
}
case ISD::CTTZ: {
- // for now, we use: { return popcount(~x & (x - 1)); }
- // but see also http://www.hackersdelight.org/HDcode/ntz.cc
+ // for now, we use: { return popcount(~x & (x - 1)); }
+ // unless the target has ctlz but not ctpop, in which case we use:
+ // { return 32 - nlz(~x & (x-1)); }
+ // see also http://www.hackersdelight.org/HDcode/ntz.cc
MVT::ValueType VT = Tmp1.getValueType();
Tmp2 = DAG.getConstant(~0ULL, VT);
Tmp3 = DAG.getNode(ISD::AND, VT,
DAG.getNode(ISD::XOR, VT, Tmp1, Tmp2),
DAG.getNode(ISD::SUB, VT, Tmp1,
DAG.getConstant(1, VT)));
- Result = LegalizeOp(DAG.getNode(ISD::CTPOP, VT, Tmp3));
+ // If ISD::CTLZ is legal and CTPOP isn't, then do that instead
+ if (TLI.getOperationAction(ISD::CTPOP, VT) != TargetLowering::Legal &&
+ TLI.getOperationAction(ISD::CTLZ, VT) == TargetLowering::Legal) {
+ Result = LegalizeOp(DAG.getNode(ISD::SUB, VT,
+ DAG.getConstant(getSizeInBits(VT), VT),
+ DAG.getNode(ISD::CTLZ, VT, Tmp3)));
+ } else {
+ Result = LegalizeOp(DAG.getNode(ISD::CTPOP, VT, Tmp3));
+ }
break;
}
default:
diff --git a/lib/Target/PowerPC/PPCISelPattern.cpp b/lib/Target/PowerPC/PPCISelPattern.cpp
index 6d687ef9f3..536a07710d 100644
--- a/lib/Target/PowerPC/PPCISelPattern.cpp
+++ b/lib/Target/PowerPC/PPCISelPattern.cpp
@@ -69,10 +69,9 @@ namespace {
setOperationAction(ISD::FCOS , MVT::f32, Expand);
setOperationAction(ISD::FSQRT, MVT::f32, Expand);
- //PowerPC has these, but they are not implemented
+ //PowerPC does not have CTPOP or CTTZ
setOperationAction(ISD::CTPOP, MVT::i32 , Expand);
setOperationAction(ISD::CTTZ , MVT::i32 , Expand);
- setOperationAction(ISD::CTLZ , MVT::i32 , Expand);
setSetCCResultContents(ZeroOrOneSetCCResult);
addLegalFPImmediate(+0.0); // Necessary for FSEL
@@ -654,9 +653,13 @@ static unsigned getImmediateForOpcode(SDOperand N, unsigned Opcode,
if ((v & 0x0000FFFF) == 0) { Imm = v >> 16; return 2; }
break;
case ISD::MUL:
- case ISD::SUB:
if (v <= 32767 && v >= -32768) { Imm = v & 0xFFFF; return 1; }
break;
+ case ISD::SUB:
+ // handle subtract-from separately from subtract, since subi is really addi
+ if (U && v <= 32767 && v >= -32768) { Imm = v & 0xFFFF; return 1; }
+ if (!U && v <= 32768 && v >= -32767) { Imm = (-v) & 0xFFFF; return 1; }
+ break;
case ISD::SETCC:
if (U && (v >= 0 && v <= 65535)) { Imm = v & 0xFFFF; return 1; }
if (!U && (v <= 32767 && v >= -32768)) { Imm = v & 0xFFFF; return 1; }
@@ -1817,6 +1820,11 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
}
return Result;
+ case ISD::CTLZ:
+ Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::CNTLZW, 1, Result).addReg(Tmp1);
+ return Result;
+
case ISD::ADD:
assert (DestType == MVT::i32 && "Only do arithmetic on i32s!");
Tmp1 = SelectExpr(N.getOperand(0));
@@ -1851,6 +1859,16 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
default: assert(0 && "unhandled result code");
case 0: // No immediate
+ // Check for andc: and, (xor a, -1), b
+ if (N.getOperand(0).getOpcode() == ISD::XOR &&
+ N.getOperand(0).getOperand(1).getOpcode() == ISD::Constant &&
+ cast<ConstantSDNode>(N.getOperand(0).getOperand(1))->isAllOnesValue()) {
+ Tmp1 = SelectExpr(N.getOperand(0).getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(1));
+ BuildMI(BB, PPC::ANDC, 2, Result).addReg(Tmp2).addReg(Tmp1);
+ return Result;
+ }
+ // It wasn't and-with-complement, emit a regular and
Tmp1 = SelectExpr(N.getOperand(0));
Tmp2 = SelectExpr(N.getOperand(1));
Opc = Recording ? PPC::ANDo : PPC::AND;
@@ -1976,11 +1994,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
}
case ISD::SUB:
- Tmp2 = SelectExpr(N.getOperand(1));
- if (1 == getImmediateForOpcode(N.getOperand(0), opcode, Tmp1))
+ if (1 == getImmediateForOpcode(N.getOperand(0), opcode, Tmp1, true)) {
+ Tmp2 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::SUBFIC, 2, Result).addReg(Tmp2).addSImm(Tmp1);
- else {
+ } else if (1 == getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
Tmp1 = SelectExpr(N.getOperand(0));
+ BuildMI(BB, PPC::ADDI, 2, Result).addReg(Tmp1).addSImm(Tmp2);
+ } else {
+ Tmp1 = SelectExpr(N.getOperand(0));
+ Tmp2 = SelectExpr(N.getOperand(1));
BuildMI(BB, PPC::SUBF, 2, Result).addReg(Tmp2).addReg(Tmp1);
}
return Result;