diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp index 8294591b73261..6ecde9b43c078 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp @@ -225,6 +225,21 @@ static bool isRegUsedByPhiNodes(unsigned DefReg, return false; } +static bool isTerminatingEHLabel(MachineBasicBlock *MBB, MachineInstr &MI) { + // Ignore non-EH labels. + if (!MI.isEHLabel()) + return false; + + // Any EH label outside a landing pad must be for an invoke. Consider it a + // terminator. + if (!MBB->isEHPad()) + return true; + + // If this is a landingpad, the first non-phi instruction will be an EH_LABEL. + // Don't consider that label to be a terminator. + return MI.getIterator() != MBB->getFirstNonPHI(); +} + /// Build a map of instruction orders. Return the first terminator and its /// order. Consider EH_LABEL instructions to be terminators as well, since local /// values for phis after invokes must be materialized before the call. @@ -233,7 +248,7 @@ void FastISel::InstOrderMap::initialize( unsigned Order = 0; for (MachineInstr &I : *MBB) { if (!FirstTerminator && - (I.isTerminator() || (I.isEHLabel() && &I != &MBB->front()))) { + (I.isTerminator() || isTerminatingEHLabel(MBB, I))) { FirstTerminator = &I; FirstTerminatorOrder = Order; } diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp index 39d16e7999cdb..1ac291fcb887c 100644 --- a/llvm/lib/Target/X86/X86AsmPrinter.cpp +++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp @@ -404,7 +404,7 @@ void X86AsmPrinter::PrintIntelMemReference(const MachineInstr *MI, static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, char Mode, raw_ostream &O) { Register Reg = MO.getReg(); - bool EmitPercent = true; + bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT; if (!X86::GR8RegClass.contains(Reg) && !X86::GR16RegClass.contains(Reg) && @@ -443,6 +443,42 @@ static bool printAsmMRegister(X86AsmPrinter &P, const MachineOperand &MO, return false; } +static bool printAsmVRegister(X86AsmPrinter &P, const MachineOperand &MO, + char Mode, raw_ostream &O) { + unsigned Reg = MO.getReg(); + bool EmitPercent = MO.getParent()->getInlineAsmDialect() == InlineAsm::AD_ATT; + + unsigned Index; + if (X86::VR128XRegClass.contains(Reg)) + Index = Reg - X86::XMM0; + else if (X86::VR256XRegClass.contains(Reg)) + Index = Reg - X86::YMM0; + else if (X86::VR512RegClass.contains(Reg)) + Index = Reg - X86::ZMM0; + else + return true; + + switch (Mode) { + default: // Unknown mode. + return true; + case 'x': // Print V4SFmode register + Reg = X86::XMM0 + Index; + break; + case 't': // Print V8SFmode register + Reg = X86::YMM0 + Index; + break; + case 'g': // Print V16SFmode register + Reg = X86::ZMM0 + Index; + break; + } + + if (EmitPercent) + O << '%'; + + O << X86ATTInstPrinter::getRegisterName(Reg); + return false; +} + /// PrintAsmOperand - Print out an operand for an inline asm expression. /// bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, @@ -517,6 +553,14 @@ bool X86AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, PrintOperand(MI, OpNo, O); return false; + case 'x': // Print V4SFmode register + case 't': // Print V8SFmode register + case 'g': // Print V16SFmode register + if (MO.isReg()) + return printAsmVRegister(*this, MO, ExtraCode[0], O); + PrintOperand(MI, OpNo, O); + return false; + case 'P': // This is the operand of a call, treat specially. PrintPCRelImm(MI, OpNo, O); return false; diff --git a/llvm/test/CodeGen/X86/asm-modifier2.ll b/llvm/test/CodeGen/X86/asm-modifier2.ll new file mode 100644 index 0000000000000..fba2f9a1e47d6 --- /dev/null +++ b/llvm/test/CodeGen/X86/asm-modifier2.ll @@ -0,0 +1,53 @@ +; RUN: llc < %s | FileCheck %s + +define void @test1() { +; CHECK-LABEL: test1: +; CHECK: vmovaps %xmm0, %xmm0 +; CHECK: vmovaps %ymm0, %ymm0 +; CHECK: vmovaps %zmm0, %zmm0 + tail call void asm sideeffect "vmovaps ${0:x}, ${0:x}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "vmovaps ${0:t}, ${0:t}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "vmovaps ${0:g}, ${0:g}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + ret void +} + +define void @test2() { +; CHECK-LABEL: test2: +; CHECK: vmovaps %xmm0, %xmm0 +; CHECK: vmovaps %ymm0, %ymm0 +; CHECK: vmovaps %zmm0, %zmm0 + tail call void asm sideeffect inteldialect "vmovaps ${0:x}, ${0:x}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "vmovaps ${0:t}, ${0:t}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "vmovaps ${0:g}, ${0:g}", "{xmm0},~{dirflag},~{fpsr},~{flags}"(i32 0) + ret void +} + +define void @test3() { +; CHECK-LABEL: test3: +; CHECK: movb %al, %al +; CHECK: movb %ah, %ah +; CHECK: movw %ax, %ax +; CHECK: movl %eax, %eax +; CHECK: movq %rax, %rax + tail call void asm sideeffect "mov ${0:b}, ${0:b}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "mov ${0:h}, ${0:h}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "mov ${0:w}, ${0:w}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "mov ${0:k}, ${0:k}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect "mov ${0:q}, ${0:q}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + ret void +} + +define void @test4() { +; CHECK-LABEL: test4: +; CHECK: movb %al, %al +; CHECK: movb %ah, %ah +; CHECK: movw %ax, %ax +; CHECK: movl %eax, %eax +; CHECK: movq %rax, %rax + tail call void asm sideeffect inteldialect "mov ${0:b}, ${0:b}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "mov ${0:h}, ${0:h}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "mov ${0:w}, ${0:w}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "mov ${0:k}, ${0:k}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + tail call void asm sideeffect inteldialect "mov ${0:q}, ${0:q}", "{eax},~{dirflag},~{fpsr},~{flags}"(i32 0) + ret void +} diff --git a/llvm/test/CodeGen/X86/inline-asm-bad-modifier.ll b/llvm/test/CodeGen/X86/inline-asm-bad-modifier.ll index 819b9fcfa7946..9f6e84f2f89c6 100644 --- a/llvm/test/CodeGen/X86/inline-asm-bad-modifier.ll +++ b/llvm/test/CodeGen/X86/inline-asm-bad-modifier.ll @@ -1,8 +1,8 @@ ; RUN: not llc -mtriple=x86_64-- < %s 2>&1 | FileCheck %s -;CHECK: error: invalid operand in inline asm: 'vmovd ${1:x}, $0' +;CHECK: error: invalid operand in inline asm: 'vmovd ${1:k}, $0' define i32 @foo() { entry: - %0 = tail call i32 asm sideeffect "vmovd ${1:x}, $0", "=r,x,~{dirflag},~{fpsr},~{flags}"(<2 x i64> ) + %0 = tail call i32 asm sideeffect "vmovd ${1:k}, $0", "=r,x,~{dirflag},~{fpsr},~{flags}"(<2 x i64> ) ret i32 %0 } diff --git a/llvm/test/CodeGen/X86/sink-local-value.ll b/llvm/test/CodeGen/X86/sink-local-value.ll index b0e511ac1189e..f7d861ac9b6ca 100644 --- a/llvm/test/CodeGen/X86/sink-local-value.ll +++ b/llvm/test/CodeGen/X86/sink-local-value.ll @@ -145,6 +145,42 @@ try.cont: ; preds = %entry, %lpad ; CHECK: retl +define i32 @lpad_phi() personality i32 (...)* @__gxx_personality_v0 { +entry: + store i32 42, i32* @sink_across + invoke void @may_throw() + to label %try.cont unwind label %lpad + +lpad: ; preds = %entry + %p = phi i32 [ 11, %entry ] ; Trivial, but -O0 keeps it + %0 = landingpad { i8*, i32 } + catch i8* null + store i32 %p, i32* @sink_across + br label %try.cont + +try.cont: ; preds = %entry, %lpad + %r.0 = phi i32 [ 13, %entry ], [ 55, %lpad ] + ret i32 %r.0 +} + +; The constant materialization should be *after* the stores to sink_across, but +; before any EH_LABEL. + +; CHECK-LABEL: lpad_phi: +; CHECK: movl $42, sink_across +; CHECK: movl $13, %{{[a-z]*}} +; CHECK: .Ltmp{{.*}}: +; CHECK: calll may_throw +; CHECK: .Ltmp{{.*}}: +; CHECK: jmp .LBB{{.*}} +; CHECK: .LBB{{.*}}: # %lpad +; CHECK-NEXT: .Ltmp{{.*}}: +; CHECK: movl {{.*}}, sink_across +; CHECK: movl $55, %{{[a-z]*}} +; CHECK: .LBB{{.*}}: # %try.cont +; CHECK: retl + + ; Function Attrs: nounwind readnone speculatable declare void @llvm.dbg.value(metadata, metadata, metadata) #0