NumVectorRegs <<= 1;
}
- MVT::ValueType VT;
- if (NumElts == 1) {
+ MVT::ValueType VT = getVectorType(EltTy, NumElts);
+ if (!isTypeLegal(VT))
VT = EltTy;
- } else {
- VT = getVectorType(EltTy, NumElts);
- }
PTyElementVT = VT;
MVT::ValueType DestVT = getTypeToTransformTo(VT);
break;
case ISD::SHL:
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
- if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask >> SA->getValue(),
+ unsigned ShAmt = SA->getValue();
+ SDOperand InOp = Op.getOperand(0);
+
+ // If this is ((X >>u C1) << ShAmt), see if we can simplify this into a
+ // single shift. We can do this if the bottom bits (which are shifted
+ // out) are never demanded.
+ if (InOp.getOpcode() == ISD::SRL &&
+ isa<ConstantSDNode>(InOp.getOperand(1))) {
+ if (ShAmt && (DemandedMask & ((1ULL << ShAmt)-1)) == 0) {
+ unsigned C1 = cast<ConstantSDNode>(InOp.getOperand(1))->getValue();
+ unsigned Opc = ISD::SHL;
+ int Diff = ShAmt-C1;
+ if (Diff < 0) {
+ Diff = -Diff;
+ Opc = ISD::SRL;
+ }
+
+ SDOperand NewSA =
+ TLO.DAG.getConstant(ShAmt-C1, Op.getOperand(1).getValueType());
+ MVT::ValueType VT = Op.getValueType();
+ return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, VT,
+ InOp.getOperand(0), NewSA));
+ }
+ }
+
+ if (SimplifyDemandedBits(Op.getOperand(0), DemandedMask >> ShAmt,
KnownZero, KnownOne, TLO, Depth+1))
return true;
KnownZero <<= SA->getValue();
if (ConstantSDNode *SA = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
MVT::ValueType VT = Op.getValueType();
unsigned ShAmt = SA->getValue();
+ uint64_t TypeMask = MVT::getIntVTBitMask(VT);
+ unsigned VTSize = MVT::getSizeInBits(VT);
+ SDOperand InOp = Op.getOperand(0);
+
+ // If this is ((X << C1) >>u ShAmt), see if we can simplify this into a
+ // single shift. We can do this if the top bits (which are shifted out)
+ // are never demanded.
+ if (InOp.getOpcode() == ISD::SHL &&
+ isa<ConstantSDNode>(InOp.getOperand(1))) {
+ if (ShAmt && (DemandedMask & (~0ULL << (VTSize-ShAmt))) == 0) {
+ unsigned C1 = cast<ConstantSDNode>(InOp.getOperand(1))->getValue();
+ unsigned Opc = ISD::SRL;
+ int Diff = ShAmt-C1;
+ if (Diff < 0) {
+ Diff = -Diff;
+ Opc = ISD::SHL;
+ }
+
+ SDOperand NewSA =
+ TLO.DAG.getConstant(Diff, Op.getOperand(1).getValueType());
+ return TLO.CombineTo(Op, TLO.DAG.getNode(Opc, VT,
+ InOp.getOperand(0), NewSA));
+ }
+ }
// Compute the new bits that are at the top now.
- uint64_t TypeMask = MVT::getIntVTBitMask(VT);
- if (SimplifyDemandedBits(Op.getOperand(0),
- (DemandedMask << ShAmt) & TypeMask,
+ if (SimplifyDemandedBits(InOp, (DemandedMask << ShAmt) & TypeMask,
KnownZero, KnownOne, TLO, Depth+1))
return true;
assert((KnownZero & KnownOne) == 0 && "Bits known to be one AND zero?");
KnownOne >>= ShAmt;
uint64_t HighBits = (1ULL << ShAmt)-1;
- HighBits <<= MVT::getSizeInBits(VT) - ShAmt;
+ HighBits <<= VTSize - ShAmt;
KnownZero |= HighBits; // High bits known zero.
}
break;
//===----------------------------------------------------------------------===//
TargetLowering::ConstraintType
-TargetLowering::getConstraintType(char ConstraintLetter) const {
+TargetLowering::getConstraintType(const std::string &Constraint) const {
// FIXME: lots more standard ones to handle.
- switch (ConstraintLetter) {
- default: return C_Unknown;
- case 'r': return C_RegisterClass;
- case 'm': // memory
- case 'o': // offsetable
- case 'V': // not offsetable
- return C_Memory;
- case 'i': // Simple Integer or Relocatable Constant
- case 'n': // Simple Integer
- case 's': // Relocatable Constant
- case 'I': // Target registers.
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- return C_Other;
+ if (Constraint.size() == 1) {
+ switch (Constraint[0]) {
+ default: break;
+ case 'r': return C_RegisterClass;
+ case 'm': // memory
+ case 'o': // offsetable
+ case 'V': // not offsetable
+ return C_Memory;
+ case 'i': // Simple Integer or Relocatable Constant
+ case 'n': // Simple Integer
+ case 's': // Relocatable Constant
+ case 'X': // Allow ANY value.
+ case 'I': // Target registers.
+ case 'J':
+ case 'K':
+ case 'L':
+ case 'M':
+ case 'N':
+ case 'O':
+ case 'P':
+ return C_Other;
+ }
}
+
+ if (Constraint.size() > 1 && Constraint[0] == '{' &&
+ Constraint[Constraint.size()-1] == '}')
+ return C_Register;
+ return C_Unknown;
}
/// isOperandValidForConstraint - Return the specified operand (possibly
case 'i': // Simple Integer or Relocatable Constant
case 'n': // Simple Integer
case 's': // Relocatable Constant
- // These are okay if the operand is either a global variable address or a
- // simple immediate value. If we have one of these, map to the TargetXXX
- // version so that the value itself doesn't get selected.
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) {
+ case 'X': { // Allows any operand.
+ // These operands are interested in values of the form (GV+C), where C may
+ // be folded in as an offset of GV, or it may be explicitly added. Also, it
+ // is possible and fine if either GV or C are missing.
+ ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
+ GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
+
+ // If we have "(add GV, C)", pull out GV/C
+ if (Op.getOpcode() == ISD::ADD) {
+ C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
+ GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
+ if (C == 0 || GA == 0) {
+ C = dyn_cast<ConstantSDNode>(Op.getOperand(0));
+ GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(1));
+ }
+ if (C == 0 || GA == 0)
+ C = 0, GA = 0;
+ }
+
+ // If we find a valid operand, map to the TargetXXX version so that the
+ // value itself doesn't get selected.
+ if (GA) { // Either &GV or &GV+C
+ if (ConstraintLetter != 'n') {
+ int64_t Offs = GA->getOffset();
+ if (C) Offs += C->getValue();
+ return DAG.getTargetGlobalAddress(GA->getGlobal(), Op.getValueType(),
+ Offs);
+ }
+ }
+ if (C) { // just C, no GV.
// Simple constants are not allowed for 's'.
if (ConstraintLetter != 's')
return DAG.getTargetConstant(C->getValue(), Op.getValueType());
}
- if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) {
- if (ConstraintLetter != 'n')
- return DAG.getTargetGlobalAddress(GA->getGlobal(), Op.getValueType(),
- GA->getOffset());
- }
break;
}
+ }
return SDOperand(0,0);
}
// Loop Strength Reduction hooks
//===----------------------------------------------------------------------===//
-/// isLegalAddressImmediate - Return true if the integer value can be used as
-/// the offset of the target addressing mode for load / store of the given
-/// type.
-bool TargetLowering::isLegalAddressImmediate(int64_t V, const Type *Ty) const {
- return false;
-}
+/// isLegalAddressingMode - Return true if the addressing mode represented
+/// by AM is legal for this target, for a load/store of the specified type.
+bool TargetLowering::isLegalAddressingMode(const AddrMode &AM,
+ const Type *Ty) const {
+ // The default implementation of this implements a conservative RISCy, r+r and
+ // r+i addr mode.
-/// isLegalAddressImmediate - Return true if the GlobalValue can be used as
-/// the offset of the target addressing mode.
-bool TargetLowering::isLegalAddressImmediate(GlobalValue *GV) const {
- return false;
-}
-
-/// isLegalAddressScale - Return true if the integer value can be used as the
-/// scale of the target addressing mode for load / store of the given type.
-bool TargetLowering::isLegalAddressScale(int64_t S, const Type *Ty) const {
- return false;
+ // Allows a sign-extended 16-bit immediate field.
+ if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1)
+ return false;
+
+ // No global is ever allowed as a base.
+ if (AM.BaseGV)
+ return false;
+
+ // Only support r+r,
+ switch (AM.Scale) {
+ case 0: // "r+i" or just "i", depending on HasBaseReg.
+ break;
+ case 1:
+ if (AM.HasBaseReg && AM.BaseOffs) // "r+r+i" is not allowed.
+ return false;
+ // Otherwise we have r+r or r+i.
+ break;
+ case 2:
+ if (AM.HasBaseReg || AM.BaseOffs) // 2*r+r or 2*r+i is not allowed.
+ return false;
+ // Allow 2*r as r+r.
+ break;
+ }
+
+ return true;
}
-
// Magic for divide replacement
struct ms {
/// multiplying by a magic number. See:
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
SDOperand TargetLowering::BuildSDIV(SDNode *N, SelectionDAG &DAG,
- std::vector<SDNode*>* Created) const {
+ std::vector<SDNode*>* Created) const {
MVT::ValueType VT = N->getValueType(0);
// Check to see if we can do this.
/// multiplying by a magic number. See:
/// <http://the.wall.riscom.net/books/proc/ppc/cwg/code2.html>
SDOperand TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
- std::vector<SDNode*>* Created) const {
+ std::vector<SDNode*>* Created) const {
MVT::ValueType VT = N->getValueType(0);
// Check to see if we can do this.
DAG.getConstant(magics.s-1, getShiftAmountTy()));
}
}
-
-MVT::ValueType TargetLowering::getValueType(const Type *Ty) const {
- switch (Ty->getTypeID()) {
- default: assert(0 && "Unknown type!");
- case Type::VoidTyID: return MVT::isVoid;
- case Type::IntegerTyID:
- switch (cast<IntegerType>(Ty)->getBitWidth()) {
- default: assert(0 && "Invalid width for value type");
- case 1: return MVT::i1;
- case 8: return MVT::i8;
- case 16: return MVT::i16;
- case 32: return MVT::i32;
- case 64: return MVT::i64;
- case 128: return MVT::i128;
- }
- break;
- case Type::FloatTyID: return MVT::f32;
- case Type::DoubleTyID: return MVT::f64;
- case Type::PointerTyID: return PointerTy;
- case Type::VectorTyID: return MVT::Vector;
- }
-}