Accessors for implicitTrap field
diff --git a/src/ir/drop.cpp b/src/ir/drop.cpp
index 0dec8ff..5b10e1a 100644
--- a/src/ir/drop.cpp
+++ b/src/ir/drop.cpp
@@ -41,7 +41,7 @@
     // Ignore a trap, as the unreachable replacement would trap too.
     if (last->is<Unreachable>()) {
       effects.mustTrap = false;
-      effects.implicitTrap = false;
+      effects.clearMayTrap();
     }
     keepParent = effects.hasUnremovableSideEffects();
   }
diff --git a/src/ir/effects.cpp b/src/ir/effects.cpp
index 68e7abc..5c401e5 100644
--- a/src/ir/effects.cpp
+++ b/src/ir/effects.cpp
@@ -84,7 +84,7 @@
   if (effects.mustTrap) {
     o << "mustTrap\n";
   }
-  if (effects.implicitTrap) {
+  if (effects.hasImplicitTrap()) {
     o << "implicitTrap\n";
   }
   if (effects.readOrder != MemoryOrder::Unordered) {
diff --git a/src/ir/effects.h b/src/ir/effects.h
index c7f6a82..0f9b337 100644
--- a/src/ir/effects.h
+++ b/src/ir/effects.h
@@ -110,14 +110,21 @@
 
   // A trap from an instruction like a load or div/rem, which may trap on corner
   // cases. If we do not ignore implicit traps then these are counted as a trap.
+  // Private to enforce using noteMayTrap().
+private:
   bool implicitTrap : 1;
 
+public:
   // Whether this code may trap, either because it is a guaranteed mustTrap,
   // or because it has an implicitTrap and we are not ignoring them.
   bool mayTrap() const {
     return mustTrap || (implicitTrap && !ignoreImplicitTraps);
   }
 
+  void noteMayTrap() { implicitTrap = true; }
+  void clearMayTrap() { implicitTrap = false; }
+  bool hasImplicitTrap() const { return implicitTrap; }
+
   bool throws_ : 1;
 
   // If this expression contains 'pop's that are not enclosed in 'catch' body.
@@ -692,7 +699,7 @@
         return true;
       }
       if (type.isNullable()) {
-        parent.implicitTrap = true;
+        parent.noteMayTrap();
       }
 
       return false;
@@ -761,7 +768,7 @@
 
       // Due to index out of bounds. Type-related traps are handled above and
       // may set either implicitTrap or trap (or neither).
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
 
       const EffectAnalyzer* callTargetEffects = nullptr;
       if (auto it = parent.module.indirectCallEffects.find(curr->heapType);
@@ -799,21 +806,21 @@
     }
     void visitLoad(Load* curr) {
       readsMemory(curr->memory, curr->order);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitStore(Store* curr) {
       writesMemory(curr->memory, curr->order);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitAtomicRMW(AtomicRMW* curr) {
       readsMemory(curr->memory, curr->order);
       writesMemory(curr->memory, curr->order);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitAtomicCmpxchg(AtomicCmpxchg* curr) {
       readsMemory(curr->memory, curr->order);
       writesMemory(curr->memory, curr->order);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitAtomicWait(AtomicWait* curr) {
       // Waits on unshared memories trap.
@@ -828,12 +835,12 @@
       parent.writesSharedMemory = true;
       parent.readOrder = parent.writeOrder = MemoryOrder::SeqCst;
       // Traps on unaligned accesses.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitAtomicNotify(AtomicNotify* curr) {
       // Notifies on unshared memories just return 0 or trap on unaligned
       // accesses.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       if (!parent.module.getMemory(curr->memory)->shared) {
         return;
       }
@@ -868,7 +875,7 @@
     void visitSIMDShift(SIMDShift* curr) {}
     void visitSIMDLoad(SIMDLoad* curr) {
       readsMemory(curr->memory, MemoryOrder::Unordered);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) {
       if (curr->isLoad()) {
@@ -876,27 +883,27 @@
       } else {
         writesMemory(curr->memory, MemoryOrder::Unordered);
       }
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitMemoryInit(MemoryInit* curr) {
       writesMemory(curr->memory, MemoryOrder::Unordered);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitDataDrop(DataDrop* curr) {
       // data.drop does not actually write memory, but it does alter the size of
       // a segment, which can be noticeable later by memory.init, so we need to
       // mark it as having a global side effect of some kind.
       parent.writesMemory = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitMemoryCopy(MemoryCopy* curr) {
       readsMemory(curr->sourceMemory, MemoryOrder::Unordered);
       writesMemory(curr->destMemory, MemoryOrder::Unordered);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitMemoryFill(MemoryFill* curr) {
       writesMemory(curr->memory, MemoryOrder::Unordered);
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitConst(Const* curr) {}
     void visitUnary(Unary* curr) {
@@ -909,7 +916,7 @@
         case TruncSFloat64ToInt64:
         case TruncUFloat64ToInt32:
         case TruncUFloat64ToInt64: {
-          parent.implicitTrap = true;
+          parent.noteMayTrap();
           break;
         }
         default: {
@@ -932,13 +939,13 @@
           // divider.
           if (auto* c = curr->right->dynCast<Const>()) {
             if (c->value.isZero()) {
-              parent.implicitTrap = true;
+              parent.noteMayTrap();
             } else if ((curr->op == DivSInt32 || curr->op == DivSInt64) &&
                        c->value.getInteger() == -1LL) {
-              parent.implicitTrap = true;
+              parent.noteMayTrap();
             }
           } else {
-            parent.implicitTrap = true;
+            parent.noteMayTrap();
           }
           break;
         }
@@ -972,11 +979,11 @@
     void visitRefEq(RefEq* curr) {}
     void visitTableGet(TableGet* curr) {
       parent.readsTable = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitTableSet(TableSet* curr) {
       parent.writesTable = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitTableSize(TableSize* curr) { parent.readsTable = true; }
     void visitTableGrow(TableGrow* curr) {
@@ -988,16 +995,16 @@
     }
     void visitTableFill(TableFill* curr) {
       parent.writesTable = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitTableCopy(TableCopy* curr) {
       parent.readsTable = true;
       parent.writesTable = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitTableInit(TableInit* curr) {
       parent.writesTable = true;
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitElemDrop(ElemDrop* curr) { parent.writesTable = true; }
     void visitTry(Try* curr) {
@@ -1046,7 +1053,7 @@
         return;
       }
       // Traps if the cast fails.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitRefGetDesc(RefGetDesc* curr) { trapOnNull(curr->ref); }
     void visitBrOn(BrOn* curr) {
@@ -1112,12 +1119,12 @@
     void visitArrayNewData(ArrayNewData* curr) {
       // Traps on out of bounds access to segments or access to dropped
       // segments.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitArrayNewElem(ArrayNewElem* curr) {
       // Traps on out of bounds access to segments or access to dropped
       // segments.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitArrayNewFixed(ArrayNewFixed* curr) {}
     void visitArrayGet(ArrayGet* curr) {
@@ -1125,7 +1132,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       readsArray(curr->ref->type.getHeapType(), curr->order);
     }
     void visitArraySet(ArraySet* curr) {
@@ -1133,7 +1140,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       writesArray(curr->ref->type.getHeapType(), curr->order);
     }
     void visitArrayLoad(ArrayLoad* curr) {
@@ -1141,7 +1148,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       readsArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
     }
 
@@ -1152,7 +1159,7 @@
       }
       parent.writesArray = true;
       // traps when the arg is null or the index out of bounds
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitArrayLen(ArrayLen* curr) {
       trapOnNull(curr->ref);
@@ -1165,7 +1172,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       readsArray(curr->srcRef->type.getHeapType(), MemoryOrder::Unordered);
       writesArray(curr->destRef->type.getHeapType(), MemoryOrder::Unordered);
     }
@@ -1174,7 +1181,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       writesArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
     }
     template<typename ArrayInit> void visitArrayInit(ArrayInit* curr) {
@@ -1183,7 +1190,7 @@
       }
       parent.writesArray = true;
       // OOB access to array or element segment.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       writesArray(curr->ref->type.getHeapType(), MemoryOrder::Unordered);
     }
     void visitArrayInitData(ArrayInitData* curr) { visitArrayInit(curr); }
@@ -1193,7 +1200,7 @@
         return;
       }
       // Null refs and OOB access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       auto heapType = curr->ref->type.getHeapType();
       readsArray(heapType, curr->order);
       writesArray(heapType, curr->order);
@@ -1216,12 +1223,12 @@
             return;
           }
           // OOB access to array.
-          parent.implicitTrap = true;
+          parent.noteMayTrap();
           parent.readsMutableArray = true;
           return;
         case StringNewFromCodePoint:
           // Invalid code points.
-          parent.implicitTrap = true;
+          parent.noteMayTrap();
           return;
       }
     }
@@ -1232,7 +1239,7 @@
         return;
       }
       // OOB array access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
       parent.writesArray = true;
     }
     void visitStringConcat(StringConcat* curr) {
@@ -1254,14 +1261,14 @@
         return;
       }
       // OOB string access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitStringSliceWTF(StringSliceWTF* curr) {
       if (trapOnNull(curr->ref)) {
         return;
       }
       // OOB string access.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitContNew(ContNew* curr) { trapOnNull(curr->func); }
     void visitContBind(ContBind* curr) {
@@ -1283,7 +1290,7 @@
       }
 
       // A suspend may go unhandled and therefore trap.
-      parent.implicitTrap = true;
+      parent.noteMayTrap();
     }
     void visitResume(Resume* curr) {
       if (trapOnNull(curr->cont)) {
diff --git a/src/passes/LocalCSE.cpp b/src/passes/LocalCSE.cpp
index 1dbff8e..4e5372c 100644
--- a/src/passes/LocalCSE.cpp
+++ b/src/passes/LocalCSE.cpp
@@ -485,7 +485,7 @@
       // example above has no effect as (ORIGINAL) never has global write
       // effects.
       effects.mustTrap = false;
-      effects.implicitTrap = false;
+      effects.clearMayTrap();
 
       auto idempotent = isIdempotent(curr, *getModule());
 
@@ -542,7 +542,7 @@
       // determinism, will ensure that either all of the appearances trap, or
       // none of them.)
       effects.mustTrap = false;
-      effects.implicitTrap = false;
+      effects.clearMayTrap();
 
       // Note that we've already checked above that this has no side effects or
       // generativity: if we got here, then it is good to go from the