summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86CallingConv.h8
-rw-r--r--llvm/lib/Target/X86/X86CallingConv.td19
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp73
3 files changed, 62 insertions, 38 deletions
diff --git a/llvm/lib/Target/X86/X86CallingConv.h b/llvm/lib/Target/X86/X86CallingConv.h
index 41fbd2e4474..2e93ec9c78c 100644
--- a/llvm/lib/Target/X86/X86CallingConv.h
+++ b/llvm/lib/Target/X86/X86CallingConv.h
@@ -41,7 +41,6 @@ inline bool CC_X86_32_VectorCallIndirect(unsigned &ValNo, MVT &ValVT,
return false; // Continue the search, but now for i32.
}
-
inline bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &,
CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
CCState &) {
@@ -51,13 +50,6 @@ inline bool CC_X86_AnyReg_Error(unsigned &, MVT &, MVT &,
return false;
}
-inline bool CC_X86_RegCall_Error(unsigned &, MVT &, MVT &,
- CCValAssign::LocInfo &, ISD::ArgFlagsTy &,
- CCState &) {
- report_fatal_error("LLVM x86 RegCall calling convention implementation" \
- " doesn't support long double and mask types yet.");
-}
-
inline bool CC_X86_32_MCUInReg(unsigned &ValNo, MVT &ValVT,
MVT &LocVT,
CCValAssign::LocInfo &LocInfo,
diff --git a/llvm/lib/Target/X86/X86CallingConv.td b/llvm/lib/Target/X86/X86CallingConv.td
index eab11196c82..a0c822ff0ab 100644
--- a/llvm/lib/Target/X86/X86CallingConv.td
+++ b/llvm/lib/Target/X86/X86CallingConv.td
@@ -76,6 +76,9 @@ def CC_#NAME : CallingConv<[
// Promote i1/i8/i16 arguments to i32.
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
+ // Promote v8i1/v16i1/v32i1 arguments to i32.
+ CCIfType<[v8i1, v16i1, v32i1], CCPromoteToType<i32>>,
+
// bool, char, int, enum, long, pointer --> GPR
CCIfType<[i32], CCAssignToReg<RC.GPR_32>>,
@@ -89,9 +92,6 @@ def CC_#NAME : CallingConv<[
CCIfSubtarget<"is32Bit()", CCIfType<[i64],
CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>,
- // TODO: Handle the case of mask types (v*i1)
- CCIfType<[v8i1, v16i1, v32i1], CCCustom<"CC_X86_RegCall_Error">>,
-
// float, double, float128 --> XMM
// In the case of SSE disabled --> save to stack
CCIfType<[f32, f64, f128],
@@ -146,8 +146,14 @@ def CC_#NAME : CallingConv<[
]>;
def RetCC_#NAME : CallingConv<[
- // Promote i1 arguments to i8.
- CCIfType<[i1], CCPromoteToType<i8>>,
+ // Promote i1, v8i1 arguments to i8.
+ CCIfType<[i1, v8i1], CCPromoteToType<i8>>,
+
+ // Promote v16i1 arguments to i16.
+ CCIfType<[v16i1], CCPromoteToType<i16>>,
+
+ // Promote v32i1 arguments to i32.
+ CCIfType<[v32i1], CCPromoteToType<i32>>,
// bool, char, int, enum, long, pointer --> GPR
CCIfType<[i8], CCAssignToReg<RC.GPR_8>>,
@@ -164,9 +170,6 @@ def RetCC_#NAME : CallingConv<[
CCIfSubtarget<"is32Bit()", CCIfType<[i64],
CCCustom<"CC_X86_32_RegCall_Assign2Regs">>>,
- // TODO: Handle the case of mask types (v*i1)
- CCIfType<[v8i1, v16i1, v32i1], CCCustom<"CC_X86_RegCall_Error">>,
-
// long double --> FP
CCIfType<[f80], CCAssignToReg<RC.FP_RET>>,
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 3e3da8b76d0..94d418c8275 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -2100,14 +2100,26 @@ const MCPhysReg *X86TargetLowering::getScratchRegisters(CallingConv::ID) const {
}
/// Lowers masks values (v*i1) to the local register values
+/// \returns DAG node after lowering to register type
static SDValue lowerMasksToReg(const SDValue &ValArg, const EVT &ValLoc,
const SDLoc &Dl, SelectionDAG &DAG) {
EVT ValVT = ValArg.getValueType();
- if (ValVT == MVT::v64i1 && ValLoc == MVT::i64) {
+ if ((ValVT == MVT::v8i1 && (ValLoc == MVT::i8 || ValLoc == MVT::i32)) ||
+ (ValVT == MVT::v16i1 && (ValLoc == MVT::i16 || ValLoc == MVT::i32))) {
+ // Two stage lowering might be required
+ // bitcast: v8i1 -> i8 / v16i1 -> i16
+ // anyextend: i8 -> i32 / i16 -> i32
+ EVT TempValLoc = ValVT == MVT::v8i1 ? MVT::i8 : MVT::i16;
+ SDValue ValToCopy = DAG.getBitcast(TempValLoc, ValArg);
+ if (ValLoc == MVT::i32)
+ ValToCopy = DAG.getNode(ISD::ANY_EXTEND, Dl, ValLoc, ValToCopy);
+ return ValToCopy;
+ } else if ((ValVT == MVT::v32i1 && ValLoc == MVT::i32) ||
+ (ValVT == MVT::v64i1 && ValLoc == MVT::i64)) {
// One stage lowering is required
- // bitcast: v64i1 -> i64
- return DAG.getBitcast(MVT::i64, ValArg);
+ // bitcast: v32i1 -> i32 / v64i1 -> i64
+ return DAG.getBitcast(ValLoc, ValArg);
} else
return DAG.getNode(ISD::SIGN_EXTEND, Dl, ValLoc, ValArg);
}
@@ -2379,14 +2391,14 @@ EVT X86TargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT,
}
/// Reads two 32 bit registers and creates a 64 bit mask value.
-/// @param VA The current 32 bit value that need to be assigned.
-/// @param NextVA The next 32 bit value that need to be assigned.
-/// @param Root The parent DAG node.
-/// @param [in,out] InFlag Represents SDvalue in the parent DAG node for
+/// \param VA The current 32 bit value that need to be assigned.
+/// \param NextVA The next 32 bit value that need to be assigned.
+/// \param Root The parent DAG node.
+/// \param [in,out] InFlag Represents SDvalue in the parent DAG node for
/// glue purposes. In the case the DAG is already using
/// physical register instead of virtual, we should glue
/// our new SDValue to InFlag SDvalue.
-/// @return a new SDvalue of size 64bit.
+/// \return a new SDvalue of size 64bit.
static SDValue getv64i1Argument(CCValAssign &VA, CCValAssign &NextVA,
SDValue &Root, SelectionDAG &DAG,
const SDLoc &Dl, const X86Subtarget &Subtarget,
@@ -2436,23 +2448,38 @@ static SDValue getv64i1Argument(CCValAssign &VA, CCValAssign &NextVA,
return DAG.getNode(ISD::CONCAT_VECTORS, Dl, MVT::v64i1, Lo, Hi);
}
+/// The function will lower a register of various sizes (8/16/32/64)
+/// to a mask value of the expected size (v8i1/v16i1/v32i1/v64i1)
+/// \returns a DAG node contains the operand after lowering to mask type.
static SDValue lowerRegToMasks(const SDValue &ValArg, const EVT &ValVT,
const EVT &ValLoc, const SDLoc &Dl,
SelectionDAG &DAG) {
- assert((ValLoc == MVT::i64 || ValLoc == MVT::i32) &&
- "Expecting register location of size 32/64 bit");
+ SDValue ValReturned = ValArg;
- // Currently not referenced - will be used in other mask lowering
- (void)Dl;
+ if (ValVT == MVT::v64i1) {
+ // In 32 bit machine, this case is handled by getv64i1Argument
+ assert(ValLoc == MVT::i64 && "Expecting only i64 locations");
+ // In 64 bit machine, There is no need to truncate the value only bitcast
+ } else {
+ MVT maskLen;
+ switch (ValVT.getSimpleVT().SimpleTy) {
+ case MVT::v8i1:
+ maskLen = MVT::i8;
+ break;
+ case MVT::v16i1:
+ maskLen = MVT::i16;
+ break;
+ case MVT::v32i1:
+ maskLen = MVT::i32;
+ break;
+ default:
+ llvm_unreachable("Expecting a vector of i1 types");
+ }
- // In the case of v64i1 no special handling is required due to two reasons:
- // In 32 bit machine, this case is handled by getv64i1Argument
- // In 64 bit machine, There is no need to truncate the value only bitcast
- if (ValVT == MVT::v64i1 && ValLoc == MVT::i32) {
- llvm_unreachable("Expecting only i64 locations");
+ ValReturned = DAG.getNode(ISD::TRUNCATE, Dl, maskLen, ValReturned);
}
- return DAG.getBitcast(ValVT, ValArg);
+ return DAG.getBitcast(ValVT, ValReturned);
}
/// Lower the result values of a call into the
@@ -2513,8 +2540,9 @@ SDValue X86TargetLowering::LowerCallResult(
if (VA.isExtInLoc() && (VA.getValVT().getScalarType() == MVT::i1)) {
if (VA.getValVT().isVector() &&
- (VA.getLocVT() == MVT::i32 || VA.getLocVT() == MVT::i64)) {
- // promoting a mask type (v*i1) into a register of type i64/i32
+ ((VA.getLocVT() == MVT::i64) || (VA.getLocVT() == MVT::i32) ||
+ (VA.getLocVT() == MVT::i16) || (VA.getLocVT() == MVT::i8))) {
+ // promoting a mask type (v*i1) into a register of type i64/i32/i16/i8
Val = lowerRegToMasks(Val, VA.getValVT(), VA.getLocVT(), dl, DAG);
} else
Val = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), Val);
@@ -2867,8 +2895,9 @@ SDValue X86TargetLowering::LowerFormalArguments(
ArgValue = DAG.getNode(X86ISD::MOVDQ2Q, dl, VA.getValVT(), ArgValue);
else if (VA.getValVT().isVector() &&
VA.getValVT().getScalarType() == MVT::i1 &&
- ((RegVT == MVT::i32) || (RegVT == MVT::i64))) {
- // Promoting a mask type (v*i1) into a register of type i64/i32
+ ((VA.getLocVT() == MVT::i64) || (VA.getLocVT() == MVT::i32) ||
+ (VA.getLocVT() == MVT::i16) || (VA.getLocVT() == MVT::i8))) {
+ // Promoting a mask type (v*i1) into a register of type i64/i32/i16/i8
ArgValue = lowerRegToMasks(ArgValue, VA.getValVT(), RegVT, dl, DAG);
} else
ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue);
OpenPOWER on IntegriCloud