diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3623,7 +3623,8 @@ CGM.getCodeGenOpts().TrapFuncName); TrapCall->addFnAttr(A); } - + if (InNoMergeAttributedStmt) + TrapCall->addFnAttr(llvm::Attribute::NoMerge); return TrapCall; } diff --git a/clang/test/CodeGen/attr-nomerge.cpp b/clang/test/CodeGen/attr-nomerge.cpp --- a/clang/test/CodeGen/attr-nomerge.cpp +++ b/clang/test/CodeGen/attr-nomerge.cpp @@ -40,6 +40,8 @@ A *newA = new B(); delete newA; + + [[clang::nomerge]] __builtin_trap(); } int g(int i); @@ -93,6 +95,7 @@ // CHECK: load ptr, ptr // CHECK: %[[AG:.*]] = load ptr, ptr // CHECK-NEXT: call void %[[AG]](ptr {{.*}}) #[[ATTR1]] +// CHECK: call void @llvm.trap() #[[ATTR0]] // CHECK: call void @_ZN1AD1Ev(ptr {{.*}}) #[[ATTR1]] // CHECK-DAG: attributes #[[ATTR0]] = {{{.*}}nomerge{{.*}}} diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -6833,22 +6833,25 @@ StringRef TrapFuncName = I.getAttributes().getFnAttr("trap-func-name").getValueAsString(); if (TrapFuncName.empty()) { + SDValue Node; switch (Intrinsic) { case Intrinsic::trap: - DAG.setRoot(DAG.getNode(ISD::TRAP, sdl, MVT::Other, getRoot())); + Node = DAG.getNode(ISD::TRAP, sdl, MVT::Other, getRoot()); break; case Intrinsic::debugtrap: - DAG.setRoot(DAG.getNode(ISD::DEBUGTRAP, sdl, MVT::Other, getRoot())); + Node = DAG.getNode(ISD::DEBUGTRAP, sdl, MVT::Other, getRoot()); break; case Intrinsic::ubsantrap: - DAG.setRoot(DAG.getNode( + Node = DAG.getNode( ISD::UBSANTRAP, sdl, MVT::Other, getRoot(), DAG.getTargetConstant( cast(I.getArgOperand(0))->getZExtValue(), sdl, - MVT::i32))); + MVT::i32)); break; default: llvm_unreachable("unknown trap intrinsic"); } + DAG.addNoMergeSiteInfo(Node.getNode(), I.hasFnAttr(Attribute::NoMerge)); + DAG.setRoot(Node); return; } TargetLowering::ArgListTy Args; diff --git a/llvm/test/CodeGen/X86/nomerge.ll b/llvm/test/CodeGen/X86/nomerge.ll --- a/llvm/test/CodeGen/X86/nomerge.ll +++ b/llvm/test/CodeGen/X86/nomerge.ll @@ -22,6 +22,28 @@ declare dso_local void @bar() +define void @nomerge_trap(i32 %i) { +entry: + switch i32 %i, label %if.end3 [ + i32 5, label %if.then + i32 7, label %if.then2 + ] + +if.then: + tail call void @llvm.trap() #0 + br label %if.end3 + +if.then2: + tail call void @llvm.trap() #0 + br label %if.end3 + +if.end3: + tail call void @llvm.trap() #0 + ret void +} + +declare dso_local void @llvm.trap() + attributes #0 = { nomerge } ; CHECK-LABEL: foo: @@ -34,3 +56,16 @@ ; CHECK: callq bar ; CHECK: .LBB0_4: # %if.end3 ; CHECK: jmp bar # TAILCALL + +; CHECK-LABEL: nomerge_trap: +; CHECK: # %bb.0: # %entry +; CHECK: # %bb.1: # %entry +; CHECK: # %bb.2: # %if.then +; CHECK-NEXT: ud2 +; CHECK-NEXT: ud2 +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB1_3: # %if.then2 +; CHECK-NEXT: ud2 +; CHECK-NEXT: .LBB1_4: # %if.end3 +; CHECK-NEXT: ud2 +; CHECK-NEXT: retq