diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -2126,6 +2126,9 @@ if (Call.isInAllocaArgument(i)) return false; // Cannot transform to and from inalloca. + if (CallerPAL.hasParamAttribute(i, Attribute::SwiftError)) + return false; + // If the parameter is passed as a byval argument, then we have to have a // sized type and the sized type has to have the same size as the old type. if (ParamTy != ActTy && CallerPAL.hasParamAttribute(i, Attribute::ByVal)) { diff --git a/llvm/test/Transforms/InstCombine/swifterror-argument-bitcast-fold.ll b/llvm/test/Transforms/InstCombine/swifterror-argument-bitcast-fold.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/swifterror-argument-bitcast-fold.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -instcombine -S %s | FileCheck %s + +; The swifterror value can only be loaded, stored or used as swifterror +; argument. Make sure we do not try to turn the function bitcast into an +; argument bitcast. +define swiftcc void @spam(i32** swifterror %arg) { +; CHECK-LABEL: @spam( +; CHECK-NEXT: bb: +; CHECK-NEXT: call swiftcc void bitcast (void (i64**)* @widget to void (i32**)*)(i32** swifterror [[ARG:%.*]]) +; CHECK-NEXT: ret void +; +bb: + call swiftcc void bitcast (void (i64**)* @widget to void (i32**)*)(i32** swifterror %arg) + ret void +} + +declare swiftcc void @widget(i64**)