Index: llvm/include/llvm/IR/Intrinsics.td =================================================================== --- llvm/include/llvm/IR/Intrinsics.td +++ llvm/include/llvm/IR/Intrinsics.td @@ -120,6 +120,8 @@ def IntrNoReturn : IntrinsicProperty; +def IntrReturnsTwice : IntrinsicProperty; + // IntrNoSync - Threads executing the intrinsic will not synchronize using // memory or other means. Applied by default. def IntrNoSync : IntrinsicProperty<1>; @@ -984,7 +986,8 @@ def int_eh_sjlj_callsite : Intrinsic<[], [llvm_i32_ty], [IntrNoMem]>; def int_eh_sjlj_functioncontext : Intrinsic<[], [llvm_ptr_ty]>; -def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; +def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], + [IntrReturnsTwice]>; def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty], [IntrNoReturn]>; def int_eh_sjlj_setup_dispatch : Intrinsic<[], []>; Index: llvm/test/CodeGen/PowerPC/sjlj.ll =================================================================== --- llvm/test/CodeGen/PowerPC/sjlj.ll +++ llvm/test/CodeGen/PowerPC/sjlj.ll @@ -72,7 +72,7 @@ ; CHECK-DAG: std 31, env_sigill@toc@l([[REG]]) ; CHECK-DAG: addi [[REGA:[0-9]+]], [[REG]], env_sigill@toc@l ; CHECK-DAG: std [[REGA]], [[OFF:[0-9]+]](31) # 8-byte Folded Spill -; CHECK-DAG: std 1, 16([[REGA]]) +; CHECK-DAG: std 4, 16([[REGA]]) ; CHECK-DAG: std 2, 24([[REGA]]) ; CHECK: bcl 20, 31, .LBB1_3 ; CHECK: li 3, 1 @@ -137,7 +137,7 @@ ; CHECK-DAG: std 31, env_sigill@toc@l([[REG]]) ; CHECK-DAG: addi [[REGB:[0-9]+]], [[REG]], env_sigill@toc@l ; CHECK-DAG: std [[REGB]], [[OFF:[0-9]+]](31) # 8-byte Folded Spill -; CHECK-DAG: std 1, 16([[REGB]]) +; CHECK-DAG: std 4, 16([[REGB]]) ; CHECK-DAG: std 2, 24([[REGB]]) ; CHECK-DAG: std 30, 32([[REGB]]) ; CHECK: bcl 20, 31, Index: llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll =================================================================== --- llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll +++ llvm/test/CodeGen/Thumb2/setjmp_longjmp.ll @@ -14,10 +14,12 @@ ; CHECK-NEXT: push.w {r4, r5, r6, r7, r8, r10, r11, lr} ; CHECK-NEXT: add r7, sp, #24 ; CHECK-NEXT: sub sp, #24 +; CHECK-NEXT: mov r0, r7 ; CHECK-NEXT: movs r1, #0 +; CHECK-NEXT: str r0, [sp, #4] +; CHECK-NEXT: mov r0, sp +; CHECK-NEXT: str r0, [sp, #12] ; CHECK-NEXT: add r0, sp, #4 -; CHECK-NEXT: str r7, [sp, #4] -; CHECK-NEXT: str.w sp, [sp, #12] ; CHECK-NEXT: mov r1, pc @ eh_setjmp begin ; CHECK-NEXT: adds r1, r1, #7 ; CHECK-NEXT: str r1, [r0, #4] @@ -35,10 +37,12 @@ ; CHECK-NEXT: movs r0, #1 ; CHECK-NEXT: str r1, [sp] @ 4-byte Spill ; CHECK-NEXT: str r0, [r1] +; CHECK-NEXT: mov r0, r7 +; CHECK-NEXT: str r0, [sp, #4] +; CHECK-NEXT: mov r0, sp +; CHECK-NEXT: str r0, [sp, #12] ; CHECK-NEXT: add r0, sp, #4 ; CHECK-NEXT: movs r1, #0 -; CHECK-NEXT: str r7, [sp, #4] -; CHECK-NEXT: str.w sp, [sp, #12] ; CHECK-NEXT: mov r1, pc @ eh_setjmp begin ; CHECK-NEXT: adds r1, r1, #7 ; CHECK-NEXT: str r1, [r0, #4] Index: llvm/test/CodeGen/X86/shadow-stack.ll =================================================================== --- llvm/test/CodeGen/X86/shadow-stack.ll +++ llvm/test/CodeGen/X86/shadow-stack.ll @@ -127,17 +127,17 @@ ; X86_64-NEXT: .cfi_offset %r13, -40 ; X86_64-NEXT: .cfi_offset %r14, -32 ; X86_64-NEXT: .cfi_offset %r15, -24 -; X86_64-NEXT: ## kill: def $edi killed $edi def $rdi -; X86_64-NEXT: movq %rdi, {{[-0-9]+}}(%r{{[sb]}}p) ## 8-byte Spill -; X86_64-NEXT: movq _buf@GOTPCREL(%rip), %rax -; X86_64-NEXT: movq (%rax), %rax -; X86_64-NEXT: movq %rbp, (%rax) -; X86_64-NEXT: movq %rsp, 16(%rax) -; X86_64-NEXT: leaq LBB1_4(%rip), %rcx -; X86_64-NEXT: movq %rcx, 8(%rax) -; X86_64-NEXT: xorq %rcx, %rcx -; X86_64-NEXT: rdsspq %rcx -; X86_64-NEXT: movq %rcx, 24(%rax) +; X86_64-NEXT: movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; X86_64-NEXT: movq %rsp, %rcx +; X86_64-NEXT: movq _buf@GOTPCREL(%rip), %rdx +; X86_64-NEXT: movq (%rdx), %rdx +; X86_64-NEXT: movq %rbp, (%rdx) +; X86_64-NEXT: movq %rcx, 16(%rdx) +; X86_64-NEXT: leaq LBB1_4(%rip), %rax +; X86_64-NEXT: movq %rax, 8(%rdx) +; X86_64-NEXT: xorq %rax, %rax +; X86_64-NEXT: rdsspq %rax +; X86_64-NEXT: movq %rax, 24(%rdx) ; X86_64-NEXT: #EH_SjLj_Setup LBB1_4 ; X86_64-NEXT: ## %bb.1: ## %entry ; X86_64-NEXT: xorl %eax, %eax @@ -149,8 +149,9 @@ ; X86_64-NEXT: testl %eax, %eax ; X86_64-NEXT: je LBB1_5 ; X86_64-NEXT: ## %bb.3: ## %if.end -; X86_64-NEXT: movq {{[-0-9]+}}(%r{{[sb]}}p), %rax ## 8-byte Reload +; X86_64-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax ## 4-byte Reload ; X86_64-NEXT: shll $2, %eax +; X86_64-NEXT: ## kill: def $eax killed $eax def $rax ; X86_64-NEXT: leal (%rax,%rax,2), %eax ; X86_64-NEXT: addq $8, %rsp ; X86_64-NEXT: popq %rbx @@ -178,14 +179,15 @@ ; X86-NEXT: .cfi_offset %esi, -20 ; X86-NEXT: .cfi_offset %edi, -16 ; X86-NEXT: .cfi_offset %ebx, -12 -; X86-NEXT: movl L_buf$non_lazy_ptr, %eax -; X86-NEXT: movl (%eax), %eax -; X86-NEXT: movl %ebp, (%eax) -; X86-NEXT: movl %esp, 16(%eax) -; X86-NEXT: movl $LBB1_4, 4(%eax) -; X86-NEXT: xorl %ecx, %ecx -; X86-NEXT: rdsspd %ecx -; X86-NEXT: movl %ecx, 12(%eax) +; X86-NEXT: movl %esp, %ecx +; X86-NEXT: movl L_buf$non_lazy_ptr, %edx +; X86-NEXT: movl (%edx), %edx +; X86-NEXT: movl %ebp, (%edx) +; X86-NEXT: movl %ecx, 16(%edx) +; X86-NEXT: movl $LBB1_4, 4(%edx) +; X86-NEXT: xorl %eax, %eax +; X86-NEXT: rdsspd %eax +; X86-NEXT: movl %eax, 12(%edx) ; X86-NEXT: #EH_SjLj_Setup LBB1_4 ; X86-NEXT: ## %bb.1: ## %entry ; X86-NEXT: xorl %eax, %eax Index: llvm/utils/TableGen/CodeGenIntrinsics.h =================================================================== --- llvm/utils/TableGen/CodeGenIntrinsics.h +++ llvm/utils/TableGen/CodeGenIntrinsics.h @@ -126,6 +126,9 @@ /// True if the intrinsic is no-return. bool isNoReturn; + /// True if the intrinsic is returns-twice. + bool isReturnsTwice; + /// True if the intrinsic is no-sync. bool isNoSync; Index: llvm/utils/TableGen/CodeGenTarget.cpp =================================================================== --- llvm/utils/TableGen/CodeGenTarget.cpp +++ llvm/utils/TableGen/CodeGenTarget.cpp @@ -666,6 +666,7 @@ isCommutative = false; canThrow = false; isNoReturn = false; + isReturnsTwice = false; isNoSync = false; isNoFree = false; isWillReturn = false; @@ -867,6 +868,8 @@ isConvergent = true; else if (R->getName() == "IntrNoReturn") isNoReturn = true; + else if (R->getName() == "IntrReturnsTwice") + isReturnsTwice = true; else if (R->getName() == "IntrNoSync") isNoSync = true; else if (R->getName() == "IntrNoFree") Index: llvm/utils/TableGen/IntrinsicEmitter.cpp =================================================================== --- llvm/utils/TableGen/IntrinsicEmitter.cpp +++ llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -590,6 +590,9 @@ if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; + if (L->isReturnsTwice != R->isReturnsTwice) + return R->isReturnsTwice; + if (L->isNoSync != R->isNoSync) return R->isNoSync; @@ -739,16 +742,18 @@ if (!Intrinsic.canThrow || (Intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem && !Intrinsic.hasSideEffects) || - Intrinsic.isNoReturn || Intrinsic.isNoSync || Intrinsic.isNoFree || - Intrinsic.isWillReturn || Intrinsic.isCold || Intrinsic.isNoDuplicate || - Intrinsic.isNoMerge || Intrinsic.isConvergent || - Intrinsic.isSpeculatable) { + Intrinsic.isNoReturn || Intrinsic.isReturnsTwice || + Intrinsic.isNoSync || Intrinsic.isNoFree || Intrinsic.isWillReturn || + Intrinsic.isCold || Intrinsic.isNoDuplicate || Intrinsic.isNoMerge || + Intrinsic.isConvergent || Intrinsic.isSpeculatable) { OS << " const Attribute::AttrKind Atts[] = {"; ListSeparator LS(","); if (!Intrinsic.canThrow) OS << LS << "Attribute::NoUnwind"; if (Intrinsic.isNoReturn) OS << LS << "Attribute::NoReturn"; + if (Intrinsic.isReturnsTwice) + OS << LS << "Attribute::ReturnsTwice"; if (Intrinsic.isNoSync) OS << LS << "Attribute::NoSync"; if (Intrinsic.isNoFree)