Index: lib/Transforms/InstCombine/InstructionCombining.cpp =================================================================== --- lib/Transforms/InstCombine/InstructionCombining.cpp +++ lib/Transforms/InstCombine/InstructionCombining.cpp @@ -2760,6 +2760,12 @@ return nullptr; } +static bool isMustTailCall(Value *V) { + if (auto *CI = dyn_cast(V)) + return CI->isMustTailCall(); + return false; +} + Instruction *InstCombiner::visitReturnInst(ReturnInst &RI) { if (RI.getNumOperands() == 0) // ret void return nullptr; @@ -2769,6 +2775,10 @@ if (!VTy->isIntegerTy() || isa(ResultOp)) return nullptr; + // Don't replace result of musttail calls. + if (isMustTailCall(ResultOp)) + return nullptr; + // There might be assume intrinsics dominating this return that completely // determine the value. If so, constant fold it. KnownBits Known = computeKnownBits(ResultOp, 0, &RI); @@ -3484,7 +3494,8 @@ // In general, it is possible for computeKnownBits to determine all bits in // a value even when the operands are not all constants. Type *Ty = I->getType(); - if (ExpensiveCombines && !I->use_empty() && Ty->isIntOrIntVectorTy()) { + if (ExpensiveCombines && !I->use_empty() && Ty->isIntOrIntVectorTy() && + !isMustTailCall(I)) { KnownBits Known = computeKnownBits(I, /*Depth*/0, I); if (Known.isConstant()) { Constant *C = ConstantInt::get(Ty, Known.getConstant()); Index: test/Transforms/InstCombine/call-returned.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/call-returned.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine -expensive-combines=0 < %s | FileCheck %s --check-prefixes=CHECK,EXPENSIVE-OFF +; RUN: opt -S -instcombine -expensive-combines=1 < %s | FileCheck %s --check-prefixes=CHECK,EXPENSIVE-ON + +declare i32 @passthru_i32(i32 returned) +declare i8* @passthru_p8(i8* returned) + +define i32 @returned_const_int_arg() { +; CHECK-LABEL: @returned_const_int_arg( +; CHECK-NEXT: [[X:%.*]] = call i32 @passthru_i32(i32 42) +; CHECK-NEXT: ret i32 42 +; + %x = call i32 @passthru_i32(i32 42) + ret i32 %x +} + +define i8* @returned_const_ptr_arg() { +; CHECK-LABEL: @returned_const_ptr_arg( +; CHECK-NEXT: [[X:%.*]] = call i8* @passthru_p8(i8* null) +; CHECK-NEXT: ret i8* [[X]] +; + %x = call i8* @passthru_p8(i8* null) + ret i8* %x +} + +define i32 @returned_var_arg(i32 %arg) { +; CHECK-LABEL: @returned_var_arg( +; CHECK-NEXT: [[X:%.*]] = call i32 @passthru_i32(i32 [[ARG:%.*]]) +; CHECK-NEXT: ret i32 [[X]] +; + %x = call i32 @passthru_i32(i32 %arg) + ret i32 %x +} + +define i32 @returned_const_int_arg_musttail(i32 %arg) { +; CHECK-LABEL: @returned_const_int_arg_musttail( +; CHECK-NEXT: [[X:%.*]] = musttail call i32 @passthru_i32(i32 42) +; CHECK-NEXT: ret i32 [[X]] +; + %x = musttail call i32 @passthru_i32(i32 42) + ret i32 %x +} + +define i32 @returned_var_arg_musttail(i32 %arg) { +; CHECK-LABEL: @returned_var_arg_musttail( +; CHECK-NEXT: [[X:%.*]] = musttail call i32 @passthru_i32(i32 [[ARG:%.*]]) +; CHECK-NEXT: ret i32 [[X]] +; + %x = musttail call i32 @passthru_i32(i32 %arg) + ret i32 %x +}