mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
TableGen: Check the dynamic type of !cast<Rec>(string)
Summary: The docs already claim that this happens, but so far it hasn't. As a consequence, existing TableGen files get this wrong a lot, but luckily the fixes are all reasonably straightforward. To make this work with all the existing forms of self-references (since the true type of a record is only built up over time), the lookup of self-references in !cast is delayed until the final resolving step. Change-Id: If5923a72a252ba2fbc81a889d59775df0ef31164 Reviewers: arsenm, craig.topper, tra, MartinO Subscribers: wdng, javed.absar, llvm-commits Differential Revision: https://reviews.llvm.org/D44475 llvm-svn: 327849
This commit is contained in:
parent
74a4d54f41
commit
a64a4772e8
@ -788,7 +788,7 @@ public:
|
||||
|
||||
// Fold - If possible, fold this to a simpler init. Return this if not
|
||||
// possible to fold.
|
||||
Init *Fold(Record *CurRec) const;
|
||||
Init *Fold(Record *CurRec, bool IsFinal = false) const;
|
||||
|
||||
Init *resolveReferences(Resolver &R) const override;
|
||||
|
||||
@ -1497,6 +1497,9 @@ public:
|
||||
|
||||
/// If there are any field references that refer to fields
|
||||
/// that have been filled in, we can propagate the values now.
|
||||
///
|
||||
/// This is a final resolve: any error messages, e.g. due to undefined
|
||||
/// !cast references, are generated now.
|
||||
void resolveReferences();
|
||||
|
||||
/// Apply the resolver to the name of the record as well as to the
|
||||
@ -1786,6 +1789,7 @@ Init *QualifyName(Record &CurRec, MultiClass *CurMultiClass,
|
||||
/// Init::resolveReferences.
|
||||
class Resolver {
|
||||
Record *CurRec;
|
||||
bool IsFinal = false;
|
||||
|
||||
public:
|
||||
explicit Resolver(Record *CurRec) : CurRec(CurRec) {}
|
||||
@ -1801,6 +1805,13 @@ public:
|
||||
// result in a ? (UnsetInit). This behavior is used to represent instruction
|
||||
// encodings by keeping references to unset variables within a record.
|
||||
virtual bool keepUnsetBits() const { return false; }
|
||||
|
||||
// Whether this is the final resolve step before adding a record to the
|
||||
// RecordKeeper. Error reporting during resolve and related constant folding
|
||||
// should only happen when this is true.
|
||||
bool isFinal() const { return IsFinal; }
|
||||
|
||||
void setFinal(bool Final) { IsFinal = Final; }
|
||||
};
|
||||
|
||||
/// Resolve arbitrary mappings.
|
||||
@ -1861,7 +1872,10 @@ class ShadowResolver final : public Resolver {
|
||||
DenseSet<Init *> Shadowed;
|
||||
|
||||
public:
|
||||
explicit ShadowResolver(Resolver &R) : Resolver(R.getCurrentRecord()), R(R) {}
|
||||
explicit ShadowResolver(Resolver &R)
|
||||
: Resolver(R.getCurrentRecord()), R(R) {
|
||||
setFinal(R.isFinal());
|
||||
}
|
||||
|
||||
void addShadow(Init *Key) { Shadowed.insert(Key); }
|
||||
|
||||
|
@ -1132,27 +1132,27 @@ def setne : PatFrag<(ops node:$lhs, node:$rhs),
|
||||
|
||||
multiclass binary_atomic_op_ord<SDNode atomic_op> {
|
||||
def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingMonotonic = 1;
|
||||
}
|
||||
def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingAcquire = 1;
|
||||
}
|
||||
def #NAME#_release : PatFrag<(ops node:$ptr, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingRelease = 1;
|
||||
}
|
||||
def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingAcquireRelease = 1;
|
||||
}
|
||||
def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingSequentiallyConsistent = 1;
|
||||
}
|
||||
@ -1160,27 +1160,27 @@ multiclass binary_atomic_op_ord<SDNode atomic_op> {
|
||||
|
||||
multiclass ternary_atomic_op_ord<SDNode atomic_op> {
|
||||
def #NAME#_monotonic : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingMonotonic = 1;
|
||||
}
|
||||
def #NAME#_acquire : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingAcquire = 1;
|
||||
}
|
||||
def #NAME#_release : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingRelease = 1;
|
||||
}
|
||||
def #NAME#_acq_rel : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingAcquireRelease = 1;
|
||||
}
|
||||
def #NAME#_seq_cst : PatFrag<(ops node:$ptr, node:$cmp, node:$val),
|
||||
(!cast<SDNode>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
(!cast<SDPatternOperator>(#NAME) node:$ptr, node:$cmp, node:$val)> {
|
||||
let IsAtomic = 1;
|
||||
let IsAtomicOrderingSequentiallyConsistent = 1;
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ void RecordRecTy::Profile(FoldingSetNodeID &ID) const {
|
||||
|
||||
std::string RecordRecTy::getAsString() const {
|
||||
if (NumClasses == 1)
|
||||
return getClasses()[0]->getName();
|
||||
return getClasses()[0]->getNameInitAsString();
|
||||
|
||||
std::string Str = "{";
|
||||
bool First = true;
|
||||
@ -202,7 +202,7 @@ std::string RecordRecTy::getAsString() const {
|
||||
if (!First)
|
||||
Str += ", ";
|
||||
First = false;
|
||||
Str += R->getName();
|
||||
Str += R->getNameInitAsString();
|
||||
}
|
||||
Str += "}";
|
||||
return Str;
|
||||
@ -700,7 +700,7 @@ void UnOpInit::Profile(FoldingSetNodeID &ID) const {
|
||||
ProfileUnOpInit(ID, getOpcode(), getOperand(), getType());
|
||||
}
|
||||
|
||||
Init *UnOpInit::Fold(Record *CurRec) const {
|
||||
Init *UnOpInit::Fold(Record *CurRec, bool IsFinal) const {
|
||||
switch (getOpcode()) {
|
||||
case CAST:
|
||||
if (isa<StringRecTy>(getType())) {
|
||||
@ -715,12 +715,34 @@ Init *UnOpInit::Fold(Record *CurRec) const {
|
||||
} else if (isa<RecordRecTy>(getType())) {
|
||||
if (StringInit *Name = dyn_cast<StringInit>(LHS)) {
|
||||
assert(CurRec && "NULL pointer");
|
||||
if (Record *D = (CurRec->getRecords()).getDef(Name->getValue()))
|
||||
return DefInit::get(D);
|
||||
Record *D;
|
||||
|
||||
PrintFatalError(CurRec->getLoc(),
|
||||
Twine("Undefined reference to record: '") +
|
||||
Name->getValue() + "'\n");
|
||||
// Self-references are allowed, but their resolution is delayed until
|
||||
// the final resolve to ensure that we get the correct type for them.
|
||||
if (Name == CurRec->getNameInit()) {
|
||||
if (!IsFinal)
|
||||
break;
|
||||
D = CurRec;
|
||||
} else {
|
||||
D = CurRec->getRecords().getDef(Name->getValue());
|
||||
if (!D) {
|
||||
if (IsFinal)
|
||||
PrintFatalError(CurRec->getLoc(),
|
||||
Twine("Undefined reference to record: '") +
|
||||
Name->getValue() + "'\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DefInit *DI = DefInit::get(D);
|
||||
if (!DI->getType()->typeIsA(getType())) {
|
||||
PrintFatalError(CurRec->getLoc(),
|
||||
Twine("Expected type '") +
|
||||
getType()->getAsString() + "', got '" +
|
||||
DI->getType()->getAsString() + "' in: " +
|
||||
getAsString() + "\n");
|
||||
}
|
||||
return DI;
|
||||
}
|
||||
}
|
||||
|
||||
@ -762,9 +784,9 @@ Init *UnOpInit::Fold(Record *CurRec) const {
|
||||
Init *UnOpInit::resolveReferences(Resolver &R) const {
|
||||
Init *lhs = LHS->resolveReferences(R);
|
||||
|
||||
if (LHS != lhs)
|
||||
if (LHS != lhs || (R.isFinal() && getOpcode() == CAST))
|
||||
return (UnOpInit::get(getOpcode(), lhs, getType()))
|
||||
->Fold(R.getCurrentRecord());
|
||||
->Fold(R.getCurrentRecord(), R.isFinal());
|
||||
return const_cast<UnOpInit *>(this);
|
||||
}
|
||||
|
||||
@ -1904,6 +1926,7 @@ void Record::resolveReferences(Resolver &R, const RecordVal *SkipVal) {
|
||||
|
||||
void Record::resolveReferences() {
|
||||
RecordResolver R(*this);
|
||||
R.setFinal(true);
|
||||
resolveReferences(R);
|
||||
}
|
||||
|
||||
|
@ -5931,10 +5931,10 @@ multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
|
||||
multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
|
||||
SDPatternOperator OpNode = null_frag> {
|
||||
def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
|
||||
(ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
|
||||
(ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
|
||||
asm, []>;
|
||||
def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
|
||||
(ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
|
||||
(ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
|
||||
asm, []>;
|
||||
}
|
||||
|
||||
@ -8789,7 +8789,7 @@ class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
|
||||
|
||||
let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
|
||||
class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
|
||||
Operand listtype>
|
||||
DAGOperand listtype>
|
||||
: BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
|
||||
(outs listtype:$Vt), (ins GPR64sp:$Rn),
|
||||
[]> {
|
||||
@ -8801,7 +8801,7 @@ class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
|
||||
}
|
||||
let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
|
||||
class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
|
||||
string asm, Operand listtype, Operand GPR64pi>
|
||||
string asm, DAGOperand listtype, DAGOperand GPR64pi>
|
||||
: BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
|
||||
"$Rn = $wback",
|
||||
(outs GPR64sp:$wback, listtype:$Vt),
|
||||
@ -8859,46 +8859,46 @@ multiclass SIMDLdrAliases<string asm, string layout, string Count,
|
||||
multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
|
||||
int Offset1, int Offset2, int Offset4, int Offset8> {
|
||||
def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
|
||||
!cast<Operand>("VecList" # Count # "8b")>;
|
||||
!cast<DAGOperand>("VecList" # Count # "8b")>;
|
||||
def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
|
||||
!cast<Operand>("VecList" # Count #"16b")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"16b")>;
|
||||
def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
|
||||
!cast<Operand>("VecList" # Count #"4h")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"4h")>;
|
||||
def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
|
||||
!cast<Operand>("VecList" # Count #"8h")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"8h")>;
|
||||
def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
|
||||
!cast<Operand>("VecList" # Count #"2s")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"2s")>;
|
||||
def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
|
||||
!cast<Operand>("VecList" # Count #"4s")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"4s")>;
|
||||
def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
|
||||
!cast<Operand>("VecList" # Count #"1d")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"1d")>;
|
||||
def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
|
||||
!cast<Operand>("VecList" # Count #"2d")>;
|
||||
!cast<DAGOperand>("VecList" # Count #"2d")>;
|
||||
|
||||
def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
|
||||
!cast<Operand>("VecList" # Count # "8b"),
|
||||
!cast<Operand>("GPR64pi" # Offset1)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "8b"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset1)>;
|
||||
def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
|
||||
!cast<Operand>("VecList" # Count # "16b"),
|
||||
!cast<Operand>("GPR64pi" # Offset1)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "16b"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset1)>;
|
||||
def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
|
||||
!cast<Operand>("VecList" # Count # "4h"),
|
||||
!cast<Operand>("GPR64pi" # Offset2)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "4h"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset2)>;
|
||||
def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
|
||||
!cast<Operand>("VecList" # Count # "8h"),
|
||||
!cast<Operand>("GPR64pi" # Offset2)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "8h"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset2)>;
|
||||
def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
|
||||
!cast<Operand>("VecList" # Count # "2s"),
|
||||
!cast<Operand>("GPR64pi" # Offset4)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "2s"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset4)>;
|
||||
def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
|
||||
!cast<Operand>("VecList" # Count # "4s"),
|
||||
!cast<Operand>("GPR64pi" # Offset4)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "4s"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset4)>;
|
||||
def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
|
||||
!cast<Operand>("VecList" # Count # "1d"),
|
||||
!cast<Operand>("GPR64pi" # Offset8)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "1d"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset8)>;
|
||||
def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
|
||||
!cast<Operand>("VecList" # Count # "2d"),
|
||||
!cast<Operand>("GPR64pi" # Offset8)>;
|
||||
!cast<DAGOperand>("VecList" # Count # "2d"),
|
||||
!cast<DAGOperand>("GPR64pi" # Offset8)>;
|
||||
|
||||
defm : SIMDLdrAliases<asm, "8b", Count, Offset1, 64>;
|
||||
defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
|
||||
@ -9300,9 +9300,9 @@ multiclass SIMDLdSt4SingleAliases<string asm> {
|
||||
let Predicates = [HasNEON, HasRDM] in {
|
||||
|
||||
class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
|
||||
RegisterOperand regtype, string asm,
|
||||
RegisterOperand regtype, string asm,
|
||||
string kind, list<dag> pattern>
|
||||
: BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
|
||||
: BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
|
||||
pattern> {
|
||||
}
|
||||
multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
|
||||
@ -9311,7 +9311,7 @@ multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
|
||||
[(set (v4i16 V64:$dst),
|
||||
(Accum (v4i16 V64:$Rd),
|
||||
(v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
|
||||
(v4i16 V64:$Rm)))))]>;
|
||||
(v4i16 V64:$Rm)))))]>;
|
||||
def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
|
||||
[(set (v8i16 V128:$dst),
|
||||
(Accum (v8i16 V128:$Rd),
|
||||
@ -9375,28 +9375,28 @@ multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
|
||||
let Inst{21} = idx{0};
|
||||
}
|
||||
|
||||
// FIXME: it would be nice to use the scalar (v1i32) instruction here, but
|
||||
// FIXME: it would be nice to use the scalar (v1i32) instruction here, but
|
||||
// an intermediate EXTRACT_SUBREG would be untyped.
|
||||
// FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
|
||||
// FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
|
||||
// got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
|
||||
def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
|
||||
(i32 (vector_extract
|
||||
(i32 (vector_extract
|
||||
(v4i32 (insert_subvector
|
||||
(undef),
|
||||
(v2i32 (int_aarch64_neon_sqrdmulh
|
||||
(undef),
|
||||
(v2i32 (int_aarch64_neon_sqrdmulh
|
||||
(v2i32 V64:$Rn),
|
||||
(v2i32 (AArch64duplane32
|
||||
(v2i32 (AArch64duplane32
|
||||
(v4i32 V128:$Rm),
|
||||
VectorIndexS:$idx)))),
|
||||
(i32 0))),
|
||||
(i64 0))))),
|
||||
(EXTRACT_SUBREG
|
||||
(v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
|
||||
(v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
|
||||
FPR32Op:$Rd,
|
||||
ssub)),
|
||||
(v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
|
||||
FPR32Op:$Rd,
|
||||
ssub)),
|
||||
V64:$Rn,
|
||||
V128:$Rm,
|
||||
V128:$Rm,
|
||||
VectorIndexS:$idx)),
|
||||
ssub)>;
|
||||
|
||||
@ -9417,26 +9417,26 @@ multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
|
||||
// FIXME: it would be nice to use the scalar (v1i32) instruction here, but
|
||||
// an intermediate EXTRACT_SUBREG would be untyped.
|
||||
def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
|
||||
(i32 (vector_extract
|
||||
(v4i32 (int_aarch64_neon_sqrdmulh
|
||||
(i32 (vector_extract
|
||||
(v4i32 (int_aarch64_neon_sqrdmulh
|
||||
(v4i32 V128:$Rn),
|
||||
(v4i32 (AArch64duplane32
|
||||
(v4i32 (AArch64duplane32
|
||||
(v4i32 V128:$Rm),
|
||||
VectorIndexS:$idx)))),
|
||||
(i64 0))))),
|
||||
(EXTRACT_SUBREG
|
||||
(v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
|
||||
(v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
|
||||
FPR32Op:$Rd,
|
||||
ssub)),
|
||||
(v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
|
||||
FPR32Op:$Rd,
|
||||
ssub)),
|
||||
V128:$Rn,
|
||||
V128:$Rm,
|
||||
V128:$Rm,
|
||||
VectorIndexS:$idx)),
|
||||
ssub)>;
|
||||
|
||||
def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
|
||||
FPR16Op, FPR16Op, V128_lo,
|
||||
VectorIndexH, asm, ".h", "", "", ".h",
|
||||
VectorIndexH, asm, ".h", "", "", ".h",
|
||||
[]> {
|
||||
bits<3> idx;
|
||||
let Inst{11} = idx{2};
|
||||
@ -9930,7 +9930,7 @@ class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
|
||||
let Predicates = [HasLSE];
|
||||
}
|
||||
|
||||
multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
|
||||
multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
|
||||
string order> {
|
||||
let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
|
||||
def B : BaseLDOPregister<op, order, "b", GPR32>;
|
||||
@ -9947,15 +9947,15 @@ multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
|
||||
let Predicates = [HasLSE] in
|
||||
multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
|
||||
string size, dag SrcRHS, dag DstRHS> {
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
|
||||
(!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
|
||||
(!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
|
||||
(!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
|
||||
(!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
|
||||
(!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
|
||||
}
|
||||
|
||||
@ -9994,15 +9994,15 @@ multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
|
||||
let Predicates = [HasLSE] in
|
||||
multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
|
||||
string size, dag OLD, dag NEW> {
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
|
||||
(!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
|
||||
(!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
|
||||
(!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
|
||||
(!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
|
||||
def : Pat<(!cast<SDNode>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
|
||||
def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
|
||||
(!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
|
||||
}
|
||||
|
||||
|
@ -500,7 +500,7 @@ let AddedComplexity = SM_LOAD_PATTERN.AddedComplexity in {
|
||||
|
||||
class SMRD_Pattern_ci <string Instr, ValueType vt> : GCNPat <
|
||||
(smrd_load (SMRDImm32 i64:$sbase, i32:$offset)),
|
||||
(vt (!cast<SM_Pseudo>(Instr#"_IMM_ci") $sbase, $offset, 0))> {
|
||||
(vt (!cast<InstSI>(Instr#"_IMM_ci") $sbase, $offset, 0))> {
|
||||
let OtherPredicates = [isCIOnly];
|
||||
}
|
||||
|
||||
|
@ -115,13 +115,13 @@ class AddressingMode<string seltype, string bitsize, string dispsize,
|
||||
class BDMode<string type, string bitsize, string dispsize, string suffix>
|
||||
: AddressingMode<type, bitsize, dispsize, suffix, "", 2, "BDAddr",
|
||||
(ops !cast<RegisterOperand>("ADDR"##bitsize),
|
||||
!cast<Immediate>("disp"##dispsize##"imm"##bitsize))>;
|
||||
!cast<Operand>("disp"##dispsize##"imm"##bitsize))>;
|
||||
|
||||
// An addressing mode with a base, displacement and index.
|
||||
class BDXMode<string type, string bitsize, string dispsize, string suffix>
|
||||
: AddressingMode<type, bitsize, dispsize, suffix, "", 3, "BDXAddr",
|
||||
(ops !cast<RegisterOperand>("ADDR"##bitsize),
|
||||
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<Operand>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<RegisterOperand>("ADDR"##bitsize))>;
|
||||
|
||||
// A BDMode paired with an immediate length operand of LENSIZE bits.
|
||||
@ -130,21 +130,21 @@ class BDLMode<string type, string bitsize, string dispsize, string suffix,
|
||||
: AddressingMode<type, bitsize, dispsize, suffix, "Len"##lensize, 3,
|
||||
"BDLAddr",
|
||||
(ops !cast<RegisterOperand>("ADDR"##bitsize),
|
||||
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<Immediate>("imm"##bitsize))>;
|
||||
!cast<Operand>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<Operand>("imm"##bitsize))>;
|
||||
|
||||
// A BDMode paired with a register length operand.
|
||||
class BDRMode<string type, string bitsize, string dispsize, string suffix>
|
||||
: AddressingMode<type, bitsize, dispsize, suffix, "", 3, "BDRAddr",
|
||||
(ops !cast<RegisterOperand>("ADDR"##bitsize),
|
||||
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<Operand>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<RegisterOperand>("GR"##bitsize))>;
|
||||
|
||||
// An addressing mode with a base, displacement and a vector index.
|
||||
class BDVMode<string bitsize, string dispsize>
|
||||
: AddressOperand<bitsize, dispsize, "", "BDVAddr",
|
||||
(ops !cast<RegisterOperand>("ADDR"##bitsize),
|
||||
!cast<Immediate>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<Operand>("disp"##dispsize##"imm"##bitsize),
|
||||
!cast<RegisterOperand>("VR128"))>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -10,5 +10,5 @@ class C<string name> {
|
||||
B b = !cast<B>(name);
|
||||
}
|
||||
|
||||
// CHECK: error: Invalid value of type 'A' is found when setting 'b' of type 'B'
|
||||
// CHECK: error: Expected type 'B', got 'A' in: !cast<B>("A0")
|
||||
def Test : C<"A0">;
|
||||
|
@ -16,6 +16,14 @@
|
||||
// CHECK: dag q = (ops C0);
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: def D0 {
|
||||
// CHECK: D d = D0;
|
||||
// CHECK: }
|
||||
|
||||
// CHECK: def E0 {
|
||||
// CHECK: E e = E0;
|
||||
// CHECK: }
|
||||
|
||||
def ops;
|
||||
|
||||
class A<dag d> {
|
||||
@ -42,3 +50,26 @@ class C<string self> {
|
||||
}
|
||||
|
||||
def C0 : C<"C0">;
|
||||
|
||||
// Explore some unused corner cases.
|
||||
//
|
||||
// A self-reference within a class may seem icky, but it unavoidably falls out
|
||||
// orthogonally of having forward class declarations and late resolve of self
|
||||
// references.
|
||||
class D<string self> {
|
||||
D d = !cast<D>(self);
|
||||
}
|
||||
|
||||
def D0 : D<"D0">;
|
||||
|
||||
class E<E x> {
|
||||
E e = x;
|
||||
}
|
||||
|
||||
// Putting the !cast directly in the def should work as well: we shouldn't
|
||||
// depend on implementation details of when exactly the record is looked up.
|
||||
//
|
||||
// Note the difference between !cast<E>("E0") and plain E0: the latter wouldn't
|
||||
// work here because E0 does not yet have E as a superclass while the template
|
||||
// arguments are being parsed.
|
||||
def E0 : E<!cast<E>("E0")>;
|
||||
|
Loading…
Reference in New Issue
Block a user