diff --git a/lib/CodeGen/MIRParser/MIParser.cpp b/lib/CodeGen/MIRParser/MIParser.cpp index c09f279a25f..5a8e96df760 100644 --- a/lib/CodeGen/MIRParser/MIParser.cpp +++ b/lib/CodeGen/MIRParser/MIParser.cpp @@ -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 Operands) { + for (const auto &I : Operands) { + if (ImplicitOperand.isIdenticalTo(I.Operand)) + return true; + } + return false; +} + bool MIParser::verifyImplicitOperands(ArrayRef Operands, const MCInstrDesc &MCID) { if (MCID.isCall()) @@ -744,46 +754,13 @@ bool MIParser::verifyImplicitOperands(ArrayRef 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; } diff --git a/test/CodeGen/MIR/PowerPC/lit.local.cfg b/test/CodeGen/MIR/PowerPC/lit.local.cfg new file mode 100644 index 00000000000..091332439b1 --- /dev/null +++ b/test/CodeGen/MIR/PowerPC/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'PowerPC' in config.root.targets: + config.unsupported = True diff --git a/test/CodeGen/MIR/PowerPC/unordered-implicit-registers.mir b/test/CodeGen/MIR/PowerPC/unordered-implicit-registers.mir new file mode 100644 index 00000000000..39d14e72ffe --- /dev/null +++ b/test/CodeGen/MIR/PowerPC/unordered-implicit-registers.mir @@ -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 +... diff --git a/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir b/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir index d2c55bdc7b8..601551a7720 100644 --- a/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir +++ b/test/CodeGen/MIR/X86/expected-different-implicit-operand.mir @@ -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: diff --git a/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir b/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir index 6a7201193a0..6494960d326 100644 --- a/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir +++ b/test/CodeGen/MIR/X86/expected-different-implicit-register-flag.mir @@ -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: