<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/140215>140215</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            InstCombine pass wrongly removes va_start/va_end
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          hongjia
      </td>
    </tr>
</table>

<pre>
    Test program:

``` C
typedef __builtin_va_list va_list;
#define va_start(ap, param) __builtin_va_start(ap, param)
#define va_end(ap) __builtin_va_end(ap)
#define va_arg(ap, type) __builtin_va_arg(ap, type)
#define va_copy(d, s) __builtin_va_copy(d, s)

int foo(int n, ...)
{
  va_list ap, aq;
  int x;

  va_start(ap, n);
  va_copy(aq, ap);
  va_end(ap);

  x = va_arg(aq, int);
  va_end(aq);

  return x + n;
}
```

Compile it with -O1:

```
clang -S -emit-llvm -O1 ic-va.c -mllvm --debug-only=instcombine

...
IC: Visiting:   call void @llvm.va_copy.p0(ptr nonnull %aq, ptr nonnull %ap)
IC: Visiting:   call void @llvm.va_end.p0(ptr %ap)
IC: ERASE   call void @llvm.va_start.p0(ptr nonnull %ap)
ADD DEFERRED:   %ap = alloca ptr, align 2
IC: ERASE   call void @llvm.va_end.p0(ptr %ap)
...
```

The resulting IR:

```
...
; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn
define dso_local i32 @foo(i32 noundef %n, ...) local_unnamed_addr #0 {
entry:
  %ap = alloca ptr, align 2
  %aq = alloca ptr, align 2
 call void @llvm.lifetime.start.p0(i64 2, ptr nonnull %ap) #3
  call void @llvm.lifetime.start.p0(i64 2, ptr nonnull %aq) #3
  call void @llvm.va_copy.p0(ptr nonnull %aq, ptr nonnull %ap)
  %0 = va_arg ptr %aq, i32
  call void @llvm.va_end.p0(ptr %aq)
  %add = add nsw i32 %0, %n
 call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %aq) #3
  call void @llvm.lifetime.end.p0(i64 2, ptr nonnull %ap) #3
  ret i32 %add
}
...
```

%ap is used in va_copy() without being initialized.

For now I use the following ugly patch to fix this:

```
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index c88710214e7e..d83228ae4b7e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -808,7 +808,10 @@ removeTriviallyEmptyRange(IntrinsicInst &EndI, InstCombinerImpl &IC,
 IC.eraseInstFromFunction(*I);
 IC.eraseInstFromFunction(EndI);
           return true;
-        }
+ } else if (EndI.getIntrinsicID() == Intrinsic::vaend &&
+ I->getIntrinsicID() == Intrinsic::vacopy &&
+ I->getArgOperand(1) == EndI.getArgOperand(0))
+          break;
         // Skip start intrinsics that don't pair with this end intrinsic.
 continue;
       }
```
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysV01v6rwS_jVmM0rkOEDSBQvKh8TqlXqqu0UmNsHnOHZqO1Dur7-aJNBA6bnn460i4WZmHs8882GHe69KI-WMTJ7JZDniTThYNztYU35XfLSz4jx7lT5A7WzpeEXSOaHtM6XdAwtC5-FcSyH3sN3uGqWDMtsj32rlA_S_JH1GI5YKuVdG4msfuAuE5bwmbAE1R3T2dAvxWOceSRrR69yZDwT3NtyVV1z0_pPtA4V7jMLWZ8JygSr-E8C9tONNmQB7awnLcWVQGMdxL86QJLhwBt3m_K0jDwAt3nsme71bggzipFeQ3gP-1sLUt8IhNx-Q70DS5YCf1lSZ8ND27dbWydA4gxDsGUwvyJbDYulUF7aqlZagApxUOED0T_K5rgidF5qbEqJvEMlKhUjrY4W6oIroyOMCoqp7FQm5a8rIGn0m6VIZHwpb7ZSRHSTyS-ebBUnn8B_lVVCmxDVAwbWGo1UCyJgiVtyzFteUsLwODow1ptEaCJt0ZNy_7Ivrl-GlER_onwBWL_Nvq69M22Q_dq0HmS-XsFytVy8vq2XnQytsk8q1tgVH_9ty0Ko0wH5t46987pi9y-7rQYKTvsE-KGHz8jC1vWX6DOvGFEFZA_MQnEdXqsaHdtxI78HYvZMSjHWyaJzHlT-bAoxtzEkZASeldVd5hM773hTebjFYDSplGEjfcSlr7XBSETYZNB-02tvGGF5JseVCYJwpha4lpQnu3MXxK4x2Om8_1_lMtFZ7GVQl40Ge1XQM7KuyQxfTdr-_BHv7P2B_3BUtE3QwU-BSQd1gSdnXO34qurcBJheio1cIMP7U5ZlNKKK2qf05w1fsP6bkN6BuU-VkuHjLhbiOyIet1JWa8tB4KUCZwVBHTByetgmwk9hpyqiguFb_lSLuzNcWHTnBBu0hHCTsrdb2hNpNqc9Q81AcIFjYq3cIB-Uf9qpQ-z1EUakCcMLWGD7-qB1h61fHjd9bV3nC1hvjw6KfvDf_LbjWPi7qGnZ_CdCeoEK-Q5HnWUJZMpaZjGORp4zlXI53mYSE0ul4TOg8iqK_9rjNwnP3_BvekzElYwpRTnPCFhmeld0yodDLnKzsUb46dVRc6_OqqsP5hZtSEpZvTHDKeFUgPBA2XRmxwaIbbOc2VY2VN90sCMPbGWwWsXTcS1RaO1tdZm5bR_PNx-H-E8Vuo-st4PrXn_rBNbKTRRdJf_azZ1yB1F6CwsHbQsWlDB_BLPuKJukSu_oqwHpM50cujcCA8OkQNxFJV78FgX3zGGPuyn9q6Xh7qUkGGBc_bxQoktDfBZ8_aNg5yX_ckUPYmrA1fPuhamjHMN6kOq88hAMPIJDaLEDNlevuQtiFgOFeVeN2llkTlLlQfEvwpVVHYpaKp_SJj-QsycZZmidP42R0mI2LYp_nNOeMTSa0kOOnbDrJKKdJPs3z6dNIzRhlEzpJpjSbMJbECU2f8iyXcpolWbrfkTGVFVc6bmefdeVIed_IWTKmLJmMNN9J7dtvCMaMPEErJYzhJ4WboVG0a0qPw1P54D9gggpazgbFCzX3Hk7OGhxQXSv4wU133Z0Mo8bp2SGEuh1ZLc-lCodmFxe2GnQp7lw7-10WaNu6ha3a-32csf8FAAD__xBH7J4">