From 2b6183d2543287e5371319d16010bf651a207b1b Mon Sep 17 00:00:00 2001 From: Torok Edwin Date: Tue, 20 Oct 2009 15:15:09 +0000 Subject: [PATCH] Fix PR4313: IPSCCP was not setting the lattice value for the invoke instruction when the invoke had multiple return values: it set the lattice value only on the extractvalue. This caused the invoke's lattice value to remain the default (undefined), and later propagated to extractvalue's operand, which incorrectly introduces undefined behavior. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84637 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SCCP.cpp | 6 +- .../SCCP/2009-06-03-sccp-structret-undef.ll | 716 ++++++++++++++++++ 2 files changed, 720 insertions(+), 2 deletions(-) create mode 100644 test/Transforms/SCCP/2009-06-03-sccp-structret-undef.ll diff --git a/lib/Transforms/Scalar/SCCP.cpp b/lib/Transforms/Scalar/SCCP.cpp index b5edf4e0582..b745097872c 100644 --- a/lib/Transforms/Scalar/SCCP.cpp +++ b/lib/Transforms/Scalar/SCCP.cpp @@ -1229,7 +1229,10 @@ CallOverdefined: TMRVI = TrackedMultipleRetVals.find(std::make_pair(F, 0)); if (TMRVI == TrackedMultipleRetVals.end()) goto CallOverdefined; - + + // Need to mark as overdefined, otherwise it stays undefined which + // creates extractvalue undef, + markOverdefined(I); // If we are tracking this callee, propagate the return values of the call // into this call site. We do this by walking all the uses. Single-index // ExtractValueInst uses can be tracked; anything more complicated is @@ -1271,7 +1274,6 @@ CallOverdefined: } } - void SCCPSolver::Solve() { // Process the work lists until they are empty! while (!BBWorkList.empty() || !InstWorkList.empty() || diff --git a/test/Transforms/SCCP/2009-06-03-sccp-structret-undef.ll b/test/Transforms/SCCP/2009-06-03-sccp-structret-undef.ll new file mode 100644 index 00000000000..4a75f463ed3 --- /dev/null +++ b/test/Transforms/SCCP/2009-06-03-sccp-structret-undef.ll @@ -0,0 +1,716 @@ +; RUN: opt -ipsccp <%s -S | FileCheck %s +; PR4313 +; the return value of a multiple-return value invoke must not be left undefined +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + +%0 = type <{ %1, %2, [4 x i8], %3 }> +%1 = type { i32 (...)**, i32, i32, i32, i32, %1*, i8*, i8*, i8* } +%2 = type { i32 } +%3 = type <{ %4, %5 }> +%4 = type { i32 (...)**, i8 } +%5 = type <{ [33 x i8], [191 x i8] }> +%6 = type { %1, %7, %10 } +%7 = type { %8 } +%8 = type { %9 } +%9 = type { i8* } +%10 = type { %11 } +%11 = type { %12 } +%12 = type { i32 (...)** } +%13 = type { %1, %14, %18, %10 } +%14 = type { %15 } +%15 = type { %16 } +%16 = type { %17 } +%17 = type { %8*, %8*, %8* } +%18 = type { %19 } +%19 = type { %20 } +%20 = type { i32*, i32*, i32* } +%21 = type { %22, %22 } +%22 = type { %23 } +%23 = type { %24 } +%24 = type { %25, %26, i64 } +%25 = type <{ i8 }> +%26 = type { i32, %26*, %26*, %26* } +%27 = type { %28, %15, i8* } +%28 = type { %29 } +%29 = type { %30 } +%30 = type { %31*, %31*, %31* } +%31 = type { %32*, %9 } +%32 = type { i32 (...)**, i8*, i8*, i8 } +%33 = type { i64, [12 x i32] } +%34 = type { %35 } +%35 = type { i32, i32, i32, i32, i32, i32, %36 } +%36 = type { %36*, %36* } +%37 = type { i32, %8, %9, %15, %38, %42 } +%38 = type { %39 } +%39 = type { %40 } +%40 = type { %41*, %41*, %41* } +%41 = type { %8, %12*, i32, %12* } +%42 = type { %43 } +%43 = type { %44 } +%44 = type { %37**, %37**, %37** } +%45 = type { i32 (...)**, i8*, i8*, i8*, i32, i8 } +%46 = type { %47, %37*, %12*, %8, %15, %37*, %50 } +%47 = type { %48 } +%48 = type { %49 } +%49 = type { i8*, i8*, i8* } +%50 = type { %51 } +%51 = type { %52 } +%52 = type { %46**, %46**, %46** } +%53 = type { %21*, %54, %63, %63, %22, %22, %22, %22, %22, %22, %37*, %37*, %37*, %72 } +%54 = type { %37*, %22, %55, %59, %18 } +%55 = type { %56 } +%56 = type { %57 } +%57 = type { %58*, %58*, %58* } +%58 = type { %37*, i32, i32 } +%59 = type { %60 } +%60 = type { %61 } +%61 = type { %62*, %62*, %62* } +%62 = type { %37*, %8, %42, %18, i32, i32, i32, %42, %8, %8 } +%63 = type { %64 } +%64 = type { %65 } +%65 = type { %66*, %66*, %66* } +%66 = type { %37*, %8, %8, %8, %8, %67, i32, i8, i8, %68 } +%67 = type { %18, %42, %18, %42 } +%68 = type { %69 } +%69 = type { %70 } +%70 = type { %71*, %71*, %71* } +%71 = type { i32, i32 } +%72 = type { %73 } +%73 = type { %74 } +%74 = type { %75*, %75*, %75* } +%75 = type { %76*, %46*, %46*, %42, i32 } +%76 = type { %77, %78 } +%77 = type { %12, %12* } +%78 = type { %79 } +%79 = type { %80 } +%80 = type { %12**, %12**, %12** } +%81 = type { %12, %21*, %53 } +%82 = type { %22, %8 } +%83 = type { %26, %84 } +%84 = type { i32, %22 } +%s2i64 = type { i64, i64 } +%85 = type { %26* } +%86 = type { %27*, i8*, %32*, i8*, i32, %8, i64, i32 } +%87 = type { %86, %88, %22, %95* } +%88 = type { %89 } +%89 = type { %90 } +%90 = type { %91*, %91*, %91* } +%91 = type { %92 } +%92 = type { %93 } +%93 = type { %94*, %94*, %94* } +%94 = type { %8, %18, %12*, %9 } +%95 = type { %37, %42 } + +@_ZNSs4_Rep20_S_empty_rep_storageE = external global [4 x i64] ; <[4 x i64]*> [#uses=1] +@.str111723 = external constant [1 x i8], align 1 ; <[1 x i8]*> [#uses=1] +@.str181730 = external constant [4 x i8], align 1 ; <[4 x i8]*> [#uses=1] +@.str721784 = external constant [37 x i8], align 8 ; <[37 x i8]*> [#uses=1] +@_ZN12_GLOBAL__N_16ActionE = external global %0, align 32 ; <%0*> [#uses=1] +@_ZN12_GLOBAL__N_114OutputFilenameE = external global %6, align 32 ; <%6*> [#uses=1] +@_ZN12_GLOBAL__N_111IncludeDirsE = external global %13, align 32 ; <%13*> [#uses=1] +@.str533653 = external constant [2 x i8], align 1 ; <[2 x i8]*> [#uses=1] +@_ZN4llvm7RecordsE = external global %21, align 32 ; <%21*> [#uses=2] +@_ZL6SrcMgr = external global %27, align 32 ; <%27*> [#uses=2] +@.str3723 = external constant [88 x i8], align 8 ; <[88 x i8]*> [#uses=1] +@.str13724 = external constant [136 x i8], align 8 ; <[136 x i8]*> [#uses=1] + +@_ZL20__gthrw_pthread_oncePiPFvvE = alias weak i32 (i32*, void ()*)* @pthread_once ; [#uses=0] +@_ZL27__gthrw_pthread_getspecificj = alias weak i8* (i32)* @pthread_getspecific ; [#uses=0] +@_ZL27__gthrw_pthread_setspecificjPKv = alias weak i32 (i32, i8*)* @pthread_setspecific ; [#uses=0] +@_ZL22__gthrw_pthread_createPmPK14pthread_attr_tPFPvS3_ES3_ = alias weak i32 (i64*, %33*, i8* (i8*)*, i8*)* @pthread_create ; [#uses=0] +@_ZL22__gthrw_pthread_cancelm = alias weak i32 (i64)* @pthread_cancel ; [#uses=0] +@_ZL26__gthrw_pthread_mutex_lockP15pthread_mutex_t = alias weak i32 (%34*)* @pthread_mutex_lock ; [#uses=0] +@_ZL29__gthrw_pthread_mutex_trylockP15pthread_mutex_t = alias weak i32 (%34*)* @pthread_mutex_trylock ; [#uses=0] +@_ZL28__gthrw_pthread_mutex_unlockP15pthread_mutex_t = alias weak i32 (%34*)* @pthread_mutex_unlock ; [#uses=0] +@_ZL26__gthrw_pthread_mutex_initP15pthread_mutex_tPK19pthread_mutexattr_t = alias weak i32 (%34*, %2*)* @pthread_mutex_init ; [#uses=0] +@_ZL26__gthrw_pthread_key_createPjPFvPvE = alias weak i32 (i32*, void (i8*)*)* @pthread_key_create ; [#uses=0] +@_ZL26__gthrw_pthread_key_deletej = alias weak i32 (i32)* @pthread_key_delete ; [#uses=0] +@_ZL30__gthrw_pthread_mutexattr_initP19pthread_mutexattr_t = alias weak i32 (%2*)* @pthread_mutexattr_init ; [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_settypeP19pthread_mutexattr_ti = alias weak i32 (%2*, i32)* @pthread_mutexattr_settype ; [#uses=0] +@_ZL33__gthrw_pthread_mutexattr_destroyP19pthread_mutexattr_t = alias weak i32 (%2*)* @pthread_mutexattr_destroy ; [#uses=0] + +declare void @_ZNSsC1EPKcRKSaIcE(%8*, i8*, %25*) + +declare i8* @_Znwm(i64) + +declare zeroext i8 @_ZNK4llvm6Record12isSubClassOfENS_9StringRefE(%37*, i64, i64) align 2 + +declare i32 @_ZNKSs7compareEPKc(%8*, i8*) + +declare %45* @_ZN4llvm11raw_ostreamlsEPKc(%45*, i8*) align 2 + +declare void @_ZNSsC1ERKSs(%8*, %8*) + +declare %26* @_ZSt18_Rb_tree_incrementPSt18_Rb_tree_node_base(%26*) + +declare void @_ZStplIcSt11char_traitsIcESaIcEESbIT_T0_T1_EPKS3_RKS6_(%8* noalias sret, i8*, %8*) + +declare %15* @_ZNSt6vectorISsSaISsEEaSERKS1_(%15*, %15*) align 2 + +declare void @_ZNSt6vectorISsSaISsEE9push_backERKSs(%15*, %8*) align 2 + +declare i32 @_ZNK4llvm15TreePatternNode10getTypeNumEj(%46*, i32) align 2 + +declare void @_ZN4llvm18CodeGenDAGPatternsD1Ev(%53*) align 2 + +declare void @_ZN4llvm18CodeGenDAGPatternsC1ERNS_12RecordKeeperE(%53*, %21*) align 2 + +declare void @_ZNK4llvm14PatternToMatch17getPredicateCheckEv(%8* noalias sret, %75*) align 2 + +define internal void @0(%81*, %45*) align 2 { + invoke void @_ZNSsC1ERKSs(%8* undef, %8* null) + to label %3 unwind label %28 + +;