mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-03-07 11:59:09 +00:00
Update GATHER instructions to support 2 read-write operands. Patch from myself and Manman Ren.
llvm-svn: 160110
This commit is contained in:
parent
e6c5349fcd
commit
6eef81b65b
@ -572,8 +572,14 @@ void X86MCCodeEmitter::EmitVEXOpcodePrefix(uint64_t TSFlags, unsigned &CurByte,
|
||||
// Classify VEX_B, VEX_4V, VEX_R, VEX_X
|
||||
unsigned NumOps = Desc.getNumOperands();
|
||||
unsigned CurOp = 0;
|
||||
if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1)
|
||||
if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) == 0)
|
||||
++CurOp;
|
||||
else if (NumOps > 3 && Desc.getOperandConstraint(2, MCOI::TIED_TO) == 0) {
|
||||
assert(Desc.getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1);
|
||||
// Special case for GATHER with 2 TIED_TO operands
|
||||
// Skip the first 2 operands: dst, mask_wb
|
||||
CurOp += 2;
|
||||
}
|
||||
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
case X86II::MRMInitReg: llvm_unreachable("FIXME: Remove this!");
|
||||
@ -971,11 +977,14 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
|
||||
// FIXME: This should be handled during MCInst lowering.
|
||||
unsigned NumOps = Desc.getNumOperands();
|
||||
unsigned CurOp = 0;
|
||||
if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) != -1)
|
||||
if (NumOps > 1 && Desc.getOperandConstraint(1, MCOI::TIED_TO) == 0)
|
||||
++CurOp;
|
||||
else if (NumOps > 2 && Desc.getOperandConstraint(NumOps-1, MCOI::TIED_TO)== 0)
|
||||
// Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
|
||||
--NumOps;
|
||||
else if (NumOps > 3 && Desc.getOperandConstraint(2, MCOI::TIED_TO) == 0) {
|
||||
assert(Desc.getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1);
|
||||
// Special case for GATHER with 2 TIED_TO operands
|
||||
// Skip the first 2 operands: dst, mask_wb
|
||||
CurOp += 2;
|
||||
}
|
||||
|
||||
// Keep track of the current byte being emitted.
|
||||
unsigned CurByte = 0;
|
||||
|
@ -935,8 +935,15 @@ void Emitter<CodeEmitter>::emitVEXOpcodePrefix(uint64_t TSFlags,
|
||||
// Classify VEX_B, VEX_4V, VEX_R, VEX_X
|
||||
unsigned NumOps = Desc->getNumOperands();
|
||||
unsigned CurOp = 0;
|
||||
if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) != -1)
|
||||
if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) == 0)
|
||||
++CurOp;
|
||||
else if (NumOps > 3 && Desc->getOperandConstraint(2, MCOI::TIED_TO) == 0) {
|
||||
assert(Desc->getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1);
|
||||
// Special case for GATHER with 2 TIED_TO operands
|
||||
// Skip the first 2 operands: dst, mask_wb
|
||||
CurOp += 2;
|
||||
}
|
||||
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
case X86II::MRMInitReg:
|
||||
// Duplicate register.
|
||||
@ -1117,11 +1124,14 @@ void Emitter<CodeEmitter>::emitInstruction(MachineInstr &MI,
|
||||
// If this is a two-address instruction, skip one of the register operands.
|
||||
unsigned NumOps = Desc->getNumOperands();
|
||||
unsigned CurOp = 0;
|
||||
if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) != -1)
|
||||
if (NumOps > 1 && Desc->getOperandConstraint(1, MCOI::TIED_TO) == 0)
|
||||
++CurOp;
|
||||
else if (NumOps > 2 && Desc->getOperandConstraint(NumOps-1,MCOI::TIED_TO)== 0)
|
||||
// Skip the last source operand that is tied_to the dest reg. e.g. LXADD32
|
||||
--NumOps;
|
||||
else if (NumOps > 3 && Desc->getOperandConstraint(2, MCOI::TIED_TO) == 0) {
|
||||
assert(Desc->getOperandConstraint(NumOps - 1, MCOI::TIED_TO) == 1);
|
||||
// Special case for GATHER with 2 TIED_TO operands
|
||||
// Skip the first 2 operands: dst, mask_wb
|
||||
CurOp += 2;
|
||||
}
|
||||
|
||||
uint64_t TSFlags = Desc->TSFlags;
|
||||
|
||||
|
@ -1966,14 +1966,22 @@ SDNode *X86DAGToDAGISel::SelectGather(SDNode *Node, unsigned Opc) {
|
||||
if (!Scale)
|
||||
return 0;
|
||||
|
||||
SDVTList VTs = CurDAG->getVTList(VSrc.getValueType(), VSrc.getValueType(),
|
||||
MVT::Other);
|
||||
|
||||
// Memory Operands: Base, Scale, Index, Disp, Segment
|
||||
SDValue Disp = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
SDValue Segment = CurDAG->getRegister(0, MVT::i32);
|
||||
const SDValue Ops[] = { VSrc, Base, getI8Imm(Scale->getSExtValue()), VIdx,
|
||||
Disp, Segment, VMask, Chain};
|
||||
SDNode *ResNode = CurDAG->getMachineNode(Opc, Node->getDebugLoc(),
|
||||
VSrc.getValueType(), MVT::Other,
|
||||
Ops, array_lengthof(Ops));
|
||||
VTs, Ops, array_lengthof(Ops));
|
||||
// Node has 2 outputs: VDst and MVT::Other.
|
||||
// ResNode has 3 outputs: VDst, VMask_wb, and MVT::Other.
|
||||
// We replace VDst of Node with VDst of ResNode, and Other of Node with Other
|
||||
// of ResNode.
|
||||
ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0));
|
||||
ReplaceUses(SDValue(Node, 1), SDValue(ResNode, 2));
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
@ -2034,7 +2042,8 @@ SDNode *X86DAGToDAGISel::Select(SDNode *Node) {
|
||||
}
|
||||
SDNode *RetVal = SelectGather(Node, Opc);
|
||||
if (RetVal)
|
||||
return RetVal;
|
||||
// We already called ReplaceUses inside SelectGather.
|
||||
return NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -8038,19 +8038,19 @@ defm VPSRAVD : avx2_var_shift<0x46, "vpsravd", sra, v4i32, v8i32>;
|
||||
// VGATHER - GATHER Operations
|
||||
multiclass avx2_gather<bits<8> opc, string OpcodeStr,
|
||||
RegisterClass RC256, X86MemOperand memop256> {
|
||||
def rm : AVX28I<opc, MRMSrcMem, (outs VR128:$dst),
|
||||
def rm : AVX28I<opc, MRMSrcMem, (outs VR128:$dst, VR128:$mask_wb),
|
||||
(ins VR128:$src1, v128mem:$src2, VR128:$mask),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$mask, $src2, $dst|$dst, $src2, $mask}"),
|
||||
[]>, VEX_4VOp3;
|
||||
def Yrm : AVX28I<opc, MRMSrcMem, (outs RC256:$dst),
|
||||
def Yrm : AVX28I<opc, MRMSrcMem, (outs RC256:$dst, RC256:$mask_wb),
|
||||
(ins RC256:$src1, memop256:$src2, RC256:$mask),
|
||||
!strconcat(OpcodeStr,
|
||||
"\t{$mask, $src2, $dst|$dst, $src2, $mask}"),
|
||||
[]>, VEX_4VOp3, VEX_L;
|
||||
}
|
||||
|
||||
let Constraints = "$src1 = $dst" in {
|
||||
let Constraints = "$src1 = $dst, $mask = $mask_wb" in {
|
||||
defm VGATHERDPD : avx2_gather<0x92, "vgatherdpd", VR256, v128mem>, VEX_W;
|
||||
defm VGATHERQPD : avx2_gather<0x93, "vgatherqpd", VR256, v256mem>, VEX_W;
|
||||
defm VGATHERDPS : avx2_gather<0x92, "vgatherdps", VR256, v256mem>;
|
||||
|
@ -1136,3 +1136,22 @@ define <4 x i32> @test_x86_avx2_gather_q_d_256(<4 x i32> %a0, i8* %a1,
|
||||
}
|
||||
declare <4 x i32> @llvm.x86.avx2.gather.q.d.256(<4 x i32>, i8*,
|
||||
<4 x i64>, <4 x i32>, i8) nounwind readonly
|
||||
|
||||
; PR13298
|
||||
define <8 x float> @test_gather_mask(<8 x float> %a0, float* %a,
|
||||
<8 x i32> %idx, <8 x float> %mask,
|
||||
float* nocapture %out) {
|
||||
; CHECK: test_gather_mask
|
||||
; CHECK: vmovdqa %ymm2, [[DEST:%.*]]
|
||||
; CHECK: vgatherdps [[DEST]]
|
||||
;; gather with mask
|
||||
%a_i8 = bitcast float* %a to i8*
|
||||
%res = call <8 x float> @llvm.x86.avx2.gather.d.ps.256(<8 x float> %a0,
|
||||
i8* %a_i8, <8 x i32> %idx, <8 x float> %mask, i8 4) ;
|
||||
|
||||
;; for debugging, we'll just dump out the mask
|
||||
%out_ptr = bitcast float * %out to <8 x float> *
|
||||
store <8 x float> %mask, <8 x float> * %out_ptr, align 4
|
||||
|
||||
ret <8 x float> %res
|
||||
}
|
||||
|
@ -277,8 +277,8 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
|
||||
}
|
||||
|
||||
void RecognizableInstr::processInstr(DisassemblerTables &tables,
|
||||
const CodeGenInstruction &insn,
|
||||
InstrUID uid)
|
||||
const CodeGenInstruction &insn,
|
||||
InstrUID uid)
|
||||
{
|
||||
// Ignore "asm parser only" instructions.
|
||||
if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
|
||||
@ -508,13 +508,13 @@ bool RecognizableInstr::has256BitOperands() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void RecognizableInstr::handleOperand(
|
||||
bool optional,
|
||||
unsigned &operandIndex,
|
||||
unsigned &physicalOperandIndex,
|
||||
unsigned &numPhysicalOperands,
|
||||
unsigned *operandMapping,
|
||||
OperandEncoding (*encodingFromString)(const std::string&, bool hasOpSizePrefix)) {
|
||||
void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
|
||||
unsigned &physicalOperandIndex,
|
||||
unsigned &numPhysicalOperands,
|
||||
const unsigned *operandMapping,
|
||||
OperandEncoding (*encodingFromString)
|
||||
(const std::string&,
|
||||
bool hasOpSizePrefix)) {
|
||||
if (optional) {
|
||||
if (physicalOperandIndex >= numPhysicalOperands)
|
||||
return;
|
||||
@ -563,7 +563,6 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
|
||||
const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands;
|
||||
|
||||
unsigned operandIndex;
|
||||
unsigned numOperands = OperandList.size();
|
||||
unsigned numPhysicalOperands = 0;
|
||||
|
||||
@ -575,12 +574,13 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
|
||||
assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
|
||||
|
||||
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
|
||||
for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
|
||||
if (OperandList[operandIndex].Constraints.size()) {
|
||||
const CGIOperandList::ConstraintInfo &Constraint =
|
||||
OperandList[operandIndex].Constraints[0];
|
||||
if (Constraint.isTied()) {
|
||||
operandMapping[operandIndex] = Constraint.getTiedOperand();
|
||||
operandMapping[operandIndex] = operandIndex;
|
||||
operandMapping[Constraint.getTiedOperand()] = operandIndex;
|
||||
} else {
|
||||
++numPhysicalOperands;
|
||||
operandMapping[operandIndex] = operandIndex;
|
||||
@ -621,7 +621,7 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||
class##EncodingFromString);
|
||||
|
||||
// operandIndex should always be < numOperands
|
||||
operandIndex = 0;
|
||||
unsigned operandIndex = 0;
|
||||
// physicalOperandIndex should always be < numPhysicalOperands
|
||||
unsigned physicalOperandIndex = 0;
|
||||
|
||||
|
@ -204,7 +204,7 @@ private:
|
||||
unsigned &operandIndex,
|
||||
unsigned &physicalOperandIndex,
|
||||
unsigned &numPhysicalOperands,
|
||||
unsigned *operandMapping,
|
||||
const unsigned *operandMapping,
|
||||
OperandEncoding (*encodingFromString)
|
||||
(const std::string&,
|
||||
bool hasOpSizePrefix));
|
||||
|
Loading…
x
Reference in New Issue
Block a user