mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-06 02:29:51 +00:00
Fix PR 24724 - The implicit register verifier shouldn't assume certain operand
order. The implicit register verifier in the MIR parser should only check if the instruction's default implicit operands are present in the instruction. It should not check the order in which they occur. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247283 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7ad3ef048d
commit
eecbba2d64
@ -724,6 +724,16 @@ static std::string getRegisterName(const TargetRegisterInfo *TRI,
|
||||
return StringRef(TRI->getName(Reg)).lower();
|
||||
}
|
||||
|
||||
/// Return true if the parsed machine operands contain a given machine operand.
|
||||
static bool isImplicitOperandIn(const MachineOperand &ImplicitOperand,
|
||||
ArrayRef<ParsedMachineOperand> Operands) {
|
||||
for (const auto &I : Operands) {
|
||||
if (ImplicitOperand.isIdenticalTo(I.Operand))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::verifyImplicitOperands(ArrayRef<ParsedMachineOperand> Operands,
|
||||
const MCInstrDesc &MCID) {
|
||||
if (MCID.isCall())
|
||||
@ -744,46 +754,13 @@ bool MIParser::verifyImplicitOperands(ArrayRef<ParsedMachineOperand> Operands,
|
||||
|
||||
const auto *TRI = MF.getSubtarget().getRegisterInfo();
|
||||
assert(TRI && "Expected target register info");
|
||||
size_t I = ImplicitOperands.size(), J = Operands.size();
|
||||
while (I) {
|
||||
--I;
|
||||
if (J) {
|
||||
--J;
|
||||
const auto &ImplicitOperand = ImplicitOperands[I];
|
||||
const auto &Operand = Operands[J].Operand;
|
||||
if (ImplicitOperand.isIdenticalTo(Operand))
|
||||
continue;
|
||||
if (Operand.isReg() && Operand.isImplicit()) {
|
||||
// Check if this implicit register is a subregister of an explicit
|
||||
// register operand.
|
||||
bool IsImplicitSubRegister = false;
|
||||
for (size_t K = 0, E = Operands.size(); K < E; ++K) {
|
||||
const auto &Op = Operands[K].Operand;
|
||||
if (Op.isReg() && !Op.isImplicit() &&
|
||||
TRI->isSubRegister(Op.getReg(), Operand.getReg())) {
|
||||
IsImplicitSubRegister = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (IsImplicitSubRegister)
|
||||
continue;
|
||||
return error(Operands[J].Begin,
|
||||
Twine("expected an implicit register operand '") +
|
||||
printImplicitRegisterFlag(ImplicitOperand) + " %" +
|
||||
getRegisterName(TRI, ImplicitOperand.getReg()) + "'");
|
||||
}
|
||||
}
|
||||
// TODO: Fix source location when Operands[J].end is right before '=', i.e:
|
||||
// insead of reporting an error at this location:
|
||||
// %eax = MOV32r0
|
||||
// ^
|
||||
// report the error at the following location:
|
||||
// %eax = MOV32r0
|
||||
// ^
|
||||
return error(J < Operands.size() ? Operands[J].End : Token.location(),
|
||||
for (const auto &I : ImplicitOperands) {
|
||||
if (isImplicitOperandIn(I, Operands))
|
||||
continue;
|
||||
return error(Operands.empty() ? Token.location() : Operands.back().End,
|
||||
Twine("missing implicit register operand '") +
|
||||
printImplicitRegisterFlag(ImplicitOperands[I]) + " %" +
|
||||
getRegisterName(TRI, ImplicitOperands[I].getReg()) + "'");
|
||||
printImplicitRegisterFlag(I) + " %" +
|
||||
getRegisterName(TRI, I.getReg()) + "'");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
2
test/CodeGen/MIR/PowerPC/lit.local.cfg
Normal file
2
test/CodeGen/MIR/PowerPC/lit.local.cfg
Normal file
@ -0,0 +1,2 @@
|
||||
if not 'PowerPC' in config.root.targets:
|
||||
config.unsupported = True
|
45
test/CodeGen/MIR/PowerPC/unordered-implicit-registers.mir
Normal file
45
test/CodeGen/MIR/PowerPC/unordered-implicit-registers.mir
Normal file
@ -0,0 +1,45 @@
|
||||
# RUN: llc -mtriple=powerpc64-unknown-linux-gnu -start-after machine-combiner -stop-after machine-combiner -o /dev/null %s | FileCheck %s
|
||||
# PR24724
|
||||
|
||||
--- |
|
||||
define signext i32 @main(i32* %p) #0 {
|
||||
entry:
|
||||
%0 = load i32, i32* %p, align 4
|
||||
%or = or i32 0, %0
|
||||
store i32 %or, i32* %p, align 4
|
||||
%lnot.1 = icmp eq i32 undef, 0
|
||||
%lnot.ext.1 = zext i1 %lnot.1 to i32
|
||||
%shr.i.1 = lshr i32 2072, %lnot.ext.1
|
||||
%call.lobit.1 = lshr i32 %shr.i.1, 7
|
||||
%1 = and i32 %call.lobit.1, 1
|
||||
%or.1 = or i32 %1, %or
|
||||
ret i32 %or.1
|
||||
}
|
||||
|
||||
attributes #0 = { nounwind "target-cpu"="ppc64" }
|
||||
...
|
||||
---
|
||||
name: main
|
||||
isSSA: true
|
||||
tracksRegLiveness: true
|
||||
registers:
|
||||
- { id: 0, class: g8rc_and_g8rc_nox0 }
|
||||
- { id: 1, class: gprc }
|
||||
- { id: 2, class: gprc }
|
||||
- { id: 3, class: gprc }
|
||||
- { id: 4, class: g8rc }
|
||||
liveins:
|
||||
- { reg: '%x3', virtual-reg: '%0' }
|
||||
body: |
|
||||
bb.0.entry:
|
||||
liveins: %x3
|
||||
|
||||
%0 = COPY %x3
|
||||
%1 = LWZ 0, %0 :: (load 4 from %ir.p)
|
||||
%2 = LI 0
|
||||
%3 = RLWIMI %2, killed %1, 0, 0, 31
|
||||
%4 = EXTSW_32_64 killed %3
|
||||
%x3 = COPY %4
|
||||
; CHECK: BLR8 implicit %lr8, implicit %rm, implicit %x3
|
||||
BLR8 implicit %lr8, implicit %rm, implicit %x3
|
||||
...
|
@ -23,7 +23,7 @@ body: |
|
||||
bb.0.entry:
|
||||
%eax = MOV32rm %rdi, 1, _, 0, _
|
||||
CMP32ri8 %eax, 10, implicit-def %eflags
|
||||
; CHECK: [[@LINE+1]]:22: expected an implicit register operand 'implicit %eflags'
|
||||
; CHECK: [[@LINE+1]]:35: missing implicit register operand 'implicit %eflags'
|
||||
JG_1 %bb.2.exit, implicit %eax
|
||||
|
||||
bb.1.less:
|
||||
|
@ -23,7 +23,7 @@ body: |
|
||||
bb.0.entry:
|
||||
%eax = MOV32rm %rdi, 1, _, 0, _
|
||||
CMP32ri8 %eax, 10, implicit-def %eflags
|
||||
; CHECK: [[@LINE+1]]:22: expected an implicit register operand 'implicit %eflags'
|
||||
; CHECK: [[@LINE+1]]:42: missing implicit register operand 'implicit %eflags'
|
||||
JG_1 %bb.2.exit, implicit-def %eflags
|
||||
|
||||
bb.1.less:
|
||||
|
Loading…
x
Reference in New Issue
Block a user