LLVM's stripPointerCasts can now look through a call/invoke (possibly with side effects) if it has a param with the 'returned' attribute
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h
index bdda7dd..23159b9 100644
--- a/lib/Target/JSBackend/CallHandlers.h
+++ b/lib/Target/JSBackend/CallHandlers.h
@@ -24,7 +24,7 @@
   // for example, extern void x() in C will turn into void x(...) in LLVM IR, then the IR bitcasts
   // it to the proper form right before the call. this both causes an unnecessary indirect
   // call, and it is done with the wrong type. TODO: don't even put it into the function table
-  if (const Function *F = dyn_cast<const Function>(CV->stripPointerCasts())) {
+  if (const Function *F = dyn_cast<const Function>(stripPointerCastsWithoutSideEffects(CV))) {
     CV = F;
   }
   return CV;
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp
index 8093570..cb0a596 100644
--- a/lib/Target/JSBackend/JSBackend.cpp
+++ b/lib/Target/JSBackend/JSBackend.cpp
@@ -299,6 +299,19 @@
     raw_pwrite_stream& nl(raw_pwrite_stream &Out, int delta = 0);
 
   private:
+
+    // LLVM changed stripPointerCasts to use the "returned" attribute on
+    // calls and invokes, i.e., stripping pointer casts of a call to
+    // define internal i8* @strupr(i8* returned %str) #2 {
+    // will return the pointer, and ignore the call which has side
+    // effects. We sometimes do care about the side effects.
+    const Value* stripPointerCastsWithoutSideEffects(const Value* V) {
+      if (isa<CallInst>(V) || isa<InvokeInst>(V)) {
+        return V; // in theory we could check if there actually are side effects
+      }
+      return V->stripPointerCasts();
+    }
+
     void printCommaSeparated(const HeapData v);
 
     // parsing of constants has two phases: calculate, and then emit
@@ -1679,7 +1692,7 @@
 
 std::string JSWriter::getValueAsStr(const Value* V, AsmCast sign) {
   // Skip past no-op bitcasts and zero-index geps.
-  V = V->stripPointerCasts();
+  V = stripPointerCastsWithoutSideEffects(V);
 
   if (const Constant *CV = dyn_cast<Constant>(V)) {
     return getConstant(CV, sign);
@@ -1690,7 +1703,7 @@
 
 std::string JSWriter::getValueAsCastStr(const Value* V, AsmCast sign) {
   // Skip past no-op bitcasts and zero-index geps.
-  V = V->stripPointerCasts();
+  V = stripPointerCastsWithoutSideEffects(V);
 
   if (isa<ConstantInt>(V) || isa<ConstantFP>(V)) {
     return getConstant(cast<Constant>(V), sign);
@@ -1701,7 +1714,7 @@
 
 std::string JSWriter::getValueAsParenStr(const Value* V) {
   // Skip past no-op bitcasts and zero-index geps.
-  V = V->stripPointerCasts();
+  V = stripPointerCastsWithoutSideEffects(V);
 
   if (const Constant *CV = dyn_cast<Constant>(V)) {
     return getConstant(CV);
@@ -1712,7 +1725,7 @@
 
 std::string JSWriter::getValueAsCastParenStr(const Value* V, AsmCast sign) {
   // Skip past no-op bitcasts and zero-index geps.
-  V = V->stripPointerCasts();
+  V = stripPointerCastsWithoutSideEffects(V);
 
   if (isa<ConstantInt>(V) || isa<ConstantFP>(V) || isa<UndefValue>(V)) {
     return getConstant(cast<Constant>(V), sign);
@@ -2362,7 +2375,7 @@
   // and all-zero-index geps that LLVM needs to satisfy its type system, we
   // call stripPointerCasts() on all values before translating them. This
   // includes bitcasts whose only use is lifetime marker intrinsics.
-  assert(I == I->stripPointerCasts());
+  assert(I == stripPointerCastsWithoutSideEffects(I));
 
   Type *T = I->getType();
   if (T->isIntegerTy() && ((!OnlyWebAssembly && T->getIntegerBitWidth() > 32) ||
@@ -2961,7 +2974,7 @@
   for (BasicBlock::const_iterator II = BB->begin(), E = BB->end();
        II != E; ++II) {
     auto I = &*II;
-    if (I->stripPointerCasts() == I) {
+    if (stripPointerCastsWithoutSideEffects(I) == I) {
       CurrInstruction = I;
       generateExpression(I, CodeStream);
     }