return std::make_pair(Interesting = true, &Bits);
}
+ case ISD::ZERO_EXTEND: {
+ // We support only the case with zero extension from i32 to i64 so far.
+ if (V.getValueType() != MVT::i64 ||
+ V.getOperand(0).getValueType() != MVT::i32)
+ break;
+
+ const SmallVector<ValueBit, 64> *LHSBits;
+ const unsigned NumOperandBits = 32;
+ std::tie(Interesting, LHSBits) = getValueBits(V.getOperand(0),
+ NumOperandBits);
+
+ for (unsigned i = 0; i < NumOperandBits; ++i)
+ Bits[i] = (*LHSBits)[i];
+
+ for (unsigned i = NumOperandBits; i < NumBits; ++i)
+ Bits[i] = ValueBit(ValueBit::ConstZero);
+
+ return std::make_pair(Interesting, &Bits);
+ }
}
for (unsigned i = 0; i < NumBits; ++i)
return ~Mask;
}
+ // This method extends an input value to 64 bit if input is 32-bit integer.
+ // While selecting instructions in BitPermutationSelector in 64-bit mode,
+ // an input value can be a 32-bit integer if a ZERO_EXTEND node is included.
+ // In such case, we extend it to 64 bit to be consistent with other values.
+ SDValue ExtendToInt64(SDValue V, const SDLoc &dl) {
+ if (V.getValueSizeInBits() == 64)
+ return V;
+
+ assert(V.getValueSizeInBits() == 32);
+ SDValue SubRegIdx = CurDAG->getTargetConstant(PPC::sub_32, dl, MVT::i32);
+ SDValue ImDef = SDValue(CurDAG->getMachineNode(PPC::IMPLICIT_DEF, dl,
+ MVT::i64), 0);
+ SDValue ExtVal = SDValue(CurDAG->getMachineNode(PPC::INSERT_SUBREG, dl,
+ MVT::i64, ImDef, V,
+ SubRegIdx), 0);
+ return ExtVal;
+ }
+
// Depending on the number of groups for a particular value, it might be
// better to rotate, mask explicitly (using andi/andis), and then or the
// result. Select this part of the result first.
assert(InstMaskStart >= 32 && "Mask cannot start out of range");
assert(InstMaskEnd >= 32 && "Mask cannot end out of range");
SDValue Ops[] =
- { V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart - 32, dl),
- getI32Imm(InstMaskEnd - 32, dl) };
+ { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLWINM8, dl, MVT::i64,
Ops), 0);
}
if (InstMaskEnd == 63) {
SDValue Ops[] =
- { V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) };
+ { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDICL, dl, MVT::i64, Ops), 0);
}
if (InstMaskStart == 0) {
SDValue Ops[] =
- { V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskEnd, dl) };
+ { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskEnd, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDICR, dl, MVT::i64, Ops), 0);
}
if (InstMaskEnd == 63 - RLAmt) {
SDValue Ops[] =
- { V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) };
+ { ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDIC, dl, MVT::i64, Ops), 0);
}
assert(InstMaskStart >= 32 && "Mask cannot start out of range");
assert(InstMaskEnd >= 32 && "Mask cannot end out of range");
SDValue Ops[] =
- { Base, V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart - 32, dl),
- getI32Imm(InstMaskEnd - 32, dl) };
+ { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskStart - 32, dl), getI32Imm(InstMaskEnd - 32, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLWIMI8, dl, MVT::i64,
Ops), 0);
}
if (InstMaskEnd == 63 - RLAmt) {
SDValue Ops[] =
- { Base, V, getI32Imm(RLAmt, dl), getI32Imm(InstMaskStart, dl) };
+ { ExtendToInt64(Base, dl), ExtendToInt64(V, dl), getI32Imm(RLAmt, dl),
+ getI32Imm(InstMaskStart, dl) };
return SDValue(CurDAG->getMachineNode(PPC::RLDIMI, dl, MVT::i64, Ops), 0);
}
SDValue ANDIVal, ANDISVal;
if (ANDIMask != 0)
ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64,
- VRot, getI32Imm(ANDIMask, dl)), 0);
+ ExtendToInt64(VRot, dl),
+ getI32Imm(ANDIMask, dl)),
+ 0);
if (ANDISMask != 0)
ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64,
- VRot, getI32Imm(ANDISMask, dl)), 0);
+ ExtendToInt64(VRot, dl),
+ getI32Imm(ANDISMask, dl)),
+ 0);
if (!ANDIVal)
TotalVal = ANDISVal;
TotalVal = ANDIVal;
else
TotalVal = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
- ANDIVal, ANDISVal), 0);
+ ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
} else {
TotalVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
TotalVal =
SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
- VRot, TotalVal), 0);
+ ExtendToInt64(VRot, dl), TotalVal),
+ 0);
}
if (!Res)
Res = TotalVal;
else
Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
- Res, TotalVal), 0);
+ ExtendToInt64(Res, dl), TotalVal),
+ 0);
// Now, remove all groups with this underlying value and rotation
// factor.
SDValue ANDIVal, ANDISVal;
if (ANDIMask != 0)
ANDIVal = SDValue(CurDAG->getMachineNode(PPC::ANDIo8, dl, MVT::i64,
- Res, getI32Imm(ANDIMask, dl)), 0);
+ ExtendToInt64(Res, dl), getI32Imm(ANDIMask, dl)), 0);
if (ANDISMask != 0)
ANDISVal = SDValue(CurDAG->getMachineNode(PPC::ANDISo8, dl, MVT::i64,
- Res, getI32Imm(ANDISMask, dl)), 0);
+ ExtendToInt64(Res, dl), getI32Imm(ANDISMask, dl)), 0);
if (!ANDIVal)
Res = ANDISVal;
Res = ANDIVal;
else
Res = SDValue(CurDAG->getMachineNode(PPC::OR8, dl, MVT::i64,
- ANDIVal, ANDISVal), 0);
+ ExtendToInt64(ANDIVal, dl), ANDISVal), 0);
} else {
if (InstCnt) *InstCnt += selectI64ImmInstrCount(Mask) + /* and */ 1;
SDValue MaskVal = SDValue(selectI64Imm(CurDAG, dl, Mask), 0);
Res =
SDValue(CurDAG->getMachineNode(PPC::AND8, dl, MVT::i64,
- Res, MaskVal), 0);
+ ExtendToInt64(Res, dl), MaskVal), 0);
}
}