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:
Alex Lorenz 2015-09-10 14:04:34 +00:00
parent 7ad3ef048d
commit eecbba2d64
5 changed files with 65 additions and 41 deletions

View File

@ -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;
}

View File

@ -0,0 +1,2 @@
if not 'PowerPC' in config.root.targets:
config.unsupported = True

View 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
...

View File

@ -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:

View File

@ -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: