diff --git a/clang/test/CodeGen/ms-inline-asm-functions.c b/clang/test/CodeGen/ms-inline-asm-functions.c --- a/clang/test/CodeGen/ms-inline-asm-functions.c +++ b/clang/test/CodeGen/ms-inline-asm-functions.c @@ -32,8 +32,20 @@ int bar(void) { // CHECK-LABEL: _bar: - __asm jmp k; - // CHECK: jmp _k + __asm { + jmp k + ja k + JAE k + LOOP k + loope k + loopne k + }; + // CHECK: jmp _k + // CHECK-NEXT: ja _k + // CHECK-NEXT: jae _k + // CHECK-NEXT: loop _k + // CHECK-NEXT: loope _k + // CHECK-NEXT: loopne _k } int baz(void) { diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3624,15 +3624,13 @@ /// legal. It is frequently not legal in PIC relocation models. virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; - /// Return true if the operand with index OpNo corresponding to a target - /// branch, for example, in following case + /// On x86, return true if the operand with index OpNo is a CALL or JUMP + /// instruction, which can use either a memory constraint or an address + /// constraint. -fasm-blocks "__asm call foo" lowers to + /// call void asm sideeffect inteldialect "call ${0:P}", "*m..." /// - /// call void asm "lea r8, $0\0A\09call qword ptr ${1:P}\0A\09ret", - /// "*m,*m,~{r8},~{dirflag},~{fpsr},~{flags}" - /// ([9 x i32]* @Arr), void (...)* @sincos_asm) - /// - /// the operand $1 (sincos_asm) is target branch in inline asm, but the - /// operand $0 (Arr) is not. + /// This function is used by a hack to choose the address constraint, + /// lowering to a direct call. virtual bool isInlineAsmTargetBranch(const SmallVectorImpl &AsmStrs, unsigned OpNo) const { diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -33944,12 +33944,9 @@ // "call dword ptr " auto TmpStr = AsmStr.substr(0, I); I = TmpStr.rfind(':'); - if (I == StringRef::npos) - return TmpStr; - - assert(I < TmpStr.size() && "Unexpected inline asm string!"); - auto Asm = TmpStr.drop_front(I + 1); - return Asm; + if (I != StringRef::npos) + TmpStr = TmpStr.substr(I + 1); + return TmpStr.take_while(llvm::isAlpha); } return StringRef(); @@ -33957,12 +33954,13 @@ bool X86TargetLowering::isInlineAsmTargetBranch( const SmallVectorImpl &AsmStrs, unsigned OpNo) const { - StringRef InstrStr = getInstrStrFromOpNo(AsmStrs, OpNo); - - if (InstrStr.contains("call")) - return true; - - return false; + // In a __asm block, __asm inst foo where inst is CALL or JMP should be + // changed from indirect TargetLowering::C_Memory to direct + // TargetLowering::C_Address. + // We don't need to special case LOOP* and Jcc, which cannot target a memory + // location. + StringRef Inst = getInstrStrFromOpNo(AsmStrs, OpNo); + return Inst.equals_insensitive("call") || Inst.equals_insensitive("jmp"); } /// Provide custom lowering hooks for some operations. diff --git a/llvm/test/CodeGen/X86/inline-asm-function-call-pic.ll b/llvm/test/CodeGen/X86/inline-asm-function-call-pic.ll --- a/llvm/test/CodeGen/X86/inline-asm-function-call-pic.ll +++ b/llvm/test/CodeGen/X86/inline-asm-function-call-pic.ll @@ -15,6 +15,7 @@ ; __asm { ; call static_func ; call extern_func +; jmp extern_func ; shr eax, 0 ; shr ebx, 0 ; shr ecx, 0 @@ -40,6 +41,7 @@ ; CHECK-EMPTY: ; CHECK-NEXT: calll static_func ; CHECK-NEXT: calll extern_func@PLT +; CHECK-NEXT: jmp extern_func@PLT ; CHECK-NEXT: shrl $0, %eax ; CHECK-NEXT: shrl $0, %ebx ; CHECK-NEXT: shrl $0, %ecx @@ -52,7 +54,8 @@ ; CHECK-NEXT: #NO_APP entry: %call = tail call i32 @static_func() - tail call void asm sideeffect inteldialect "call dword ptr ${0:P}\0A\09call dword ptr ${1:P}\0A\09shr eax, $$0\0A\09shr ebx, $$0\0A\09shr ecx, $$0\0A\09shr edx, $$0\0A\09shr edi, $$0\0A\09shr esi, $$0\0A\09shr ebp, $$0\0A\09shr esp, $$0", "*m,*m,~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32 (...)) @static_func, ptr nonnull elementtype(i32 (...)) @extern_func) #0 +;; We test call, CALL, and jmp. + tail call void asm sideeffect inteldialect "call ${0:P}\0A\09CALL ${1:P}\0A\09jmp ${1:P}\0A\09shr eax, $$0\0A\09shr ebx, $$0\0A\09shr ecx, $$0\0A\09shr edx, $$0\0A\09shr edi, $$0\0A\09shr esi, $$0\0A\09shr ebp, $$0\0A\09shr esp, $$0", "*m,*m,~{eax},~{ebp},~{ebx},~{ecx},~{edi},~{edx},~{flags},~{esi},~{esp},~{dirflag},~{fpsr},~{flags}"(ptr nonnull elementtype(i32 (...)) @static_func, ptr nonnull elementtype(i32 (...)) @extern_func) #0 ret void }