diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -946,6 +946,22 @@ /// integer type VT, by either zero-extending or truncating it. SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + /// Convert Op, which must be of integer type, to the + /// integer type VT, by either any/sign/zero-extending (depending on IsAny / + /// IsSigned) or truncating it. + SDValue getExtOrTrunc(SDValue Op, const SDLoc &DL, + EVT VT, unsigned Opcode) { + switch(Opcode) { + case ISD::ANY_EXTEND: + return getAnyExtOrTrunc(Op, DL, VT); + case ISD::ZERO_EXTEND: + return getZExtOrTrunc(Op, DL, VT); + case ISD::SIGN_EXTEND: + return getSExtOrTrunc(Op, DL, VT); + } + llvm_unreachable("Unsupported opcode"); + } + /// Convert Op, which must be of integer type, to the /// integer type VT, by either sign/zero-extending (depending on IsSigned) or /// truncating it. @@ -953,6 +969,21 @@ return IsSigned ? getSExtOrTrunc(Op, DL, VT) : getZExtOrTrunc(Op, DL, VT); } + /// Convert Op, which must be of integer type, to the + /// integer type VT, by first bitcasting (from potential vector) to + /// corresponding scalar type then either any-extending or truncating it. + SDValue getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + + /// Convert Op, which must be of integer type, to the + /// integer type VT, by first bitcasting (from potential vector) to + /// corresponding scalar type then either sign-extending or truncating it. + SDValue getBitcastedSExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + + /// Convert Op, which must be of integer type, to the + /// integer type VT, by first bitcasting (from potential vector) to + /// corresponding scalar type then either zero-extending or truncating it. + SDValue getBitcastedZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT); + /// Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, const SDLoc &DL, EVT VT); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1453,6 +1453,51 @@ getNode(ISD::TRUNCATE, DL, VT, Op); } +SDValue SelectionDAG::getBitcastedAnyExtOrTrunc(SDValue Op, const SDLoc &DL, + EVT VT) { + assert(!VT.isVector()); + auto Type = Op.getValueType(); + SDValue DestOp; + if (Type == VT) + return Op; + auto Size = Op.getValueSizeInBits(); + DestOp = getBitcast(MVT::getIntegerVT(Size), Op); + if (DestOp.getValueType() == VT) + return DestOp; + + return getAnyExtOrTrunc(DestOp, DL, VT); +} + +SDValue SelectionDAG::getBitcastedSExtOrTrunc(SDValue Op, const SDLoc &DL, + EVT VT) { + assert(!VT.isVector()); + auto Type = Op.getValueType(); + SDValue DestOp; + if (Type == VT) + return Op; + auto Size = Op.getValueSizeInBits(); + DestOp = getBitcast(MVT::getIntegerVT(Size), Op); + if (DestOp.getValueType() == VT) + return DestOp; + + return getSExtOrTrunc(DestOp, DL, VT); +} + +SDValue SelectionDAG::getBitcastedZExtOrTrunc(SDValue Op, const SDLoc &DL, + EVT VT) { + assert(!VT.isVector()); + auto Type = Op.getValueType(); + SDValue DestOp; + if (Type == VT) + return Op; + auto Size = Op.getValueSizeInBits(); + DestOp = getBitcast(MVT::getIntegerVT(Size), Op); + if (DestOp.getValueType() == VT) + return DestOp; + + return getZExtOrTrunc(DestOp, DL, VT); +} + SDValue SelectionDAG::getBoolExtOrTrunc(SDValue Op, const SDLoc &SL, EVT VT, EVT OpVT) { if (VT.bitsLE(Op.getValueType())) diff --git a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp --- a/llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ b/llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -10943,21 +10943,13 @@ assert(Op.getValueType().isByteSized() && OtherOp.getValueType().isByteSized()); - // Handle potential vectors - Op = DAG.getBitcast(MVT::getIntegerVT(Op.getValueSizeInBits()), Op); - OtherOp = DAG.getBitcast( - MVT::getIntegerVT(OtherOp.getValueSizeInBits()), OtherOp); - - if (Op.getValueSizeInBits() < 32) - // If the ultimate src is less than 32 bits, then we will only be - // using bytes 0: Op.getValueSizeInBytes() - 1 in the or. - // CalculateByteProvider would not have returned Op as source if we - // used a byte that is outside its ValueType. Thus, we are free to - // ANY_EXTEND as the extended bits are dont-cares. - Op = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, Op); - - if (OtherOp.getValueSizeInBits() < 32) - OtherOp = DAG.getNode(ISD::ANY_EXTEND, DL, MVT::i32, OtherOp); + // If the ultimate src is less than 32 bits, then we will only be + // using bytes 0: Op.getValueSizeInBytes() - 1 in the or. + // CalculateByteProvider would not have returned Op as source if we + // used a byte that is outside its ValueType. Thus, we are free to + // ANY_EXTEND as the extended bits are dont-cares. + Op = DAG.getBitcastedAnyExtOrTrunc(Op, DL, MVT::i32); + OtherOp = DAG.getBitcastedAnyExtOrTrunc(OtherOp, DL, MVT::i32); return DAG.getNode(AMDGPUISD::PERM, DL, MVT::i32, Op, OtherOp, DAG.getConstant(PermMask, DL, MVT::i32));