void removeMSSA(Instruction *Inst) {
if (!MSSA)
return;
- // FIXME: Removing a store here can leave MemorySSA in an unoptimized state
- // by creating MemoryPhis that have identical arguments and by creating
+ // Removing a store here can leave MemorySSA in an unoptimized state by
+ // creating MemoryPhis that have identical arguments and by creating
// MemoryUses whose defining access is not an actual clobber. We handle the
- // phi case here, but the non-optimized MemoryUse case is not handled. Once
- // MemorySSA tracks whether uses are optimized this will be taken care of on
- // the MemorySSA side.
+ // phi case eagerly here. The non-optimized MemoryUse case is lazily
+ // updated by MemorySSA getClobberingMemoryAccess.
if (MemoryAccess *MA = MSSA->getMemoryAccess(Inst)) {
// Optimize MemoryPhi nodes that may become redundant by having all the
// same input values once MA is removed.
// LaterInst, if LaterDef dominates EarlierInst then it can't occur between
// EarlierInst and LaterInst and neither can any other write that potentially
// clobbers LaterInst.
- // FIXME: Use getClobberingMemoryAccess only for stores since it is currently
- // fairly expensive to call on MemoryUses since it does an AA check even for
- // MemoryUses that were already optimized by MemorySSA construction. Once
- // MemorySSA optimized use tracking change has been committed we can use
- // getClobberingMemoryAccess for MemoryUses as well.
- MemoryAccess *LaterMA = MSSA->getMemoryAccess(LaterInst);
- MemoryAccess *LaterDef;
- if (auto *LaterUse = dyn_cast<MemoryUse>(LaterMA))
- LaterDef = LaterUse->getDefiningAccess();
- else
- LaterDef = MSSA->getWalker()->getClobberingMemoryAccess(LaterInst);
+ MemoryAccess *LaterDef =
+ MSSA->getWalker()->getClobberingMemoryAccess(LaterInst);
return MSSA->dominates(LaterDef, MSSA->getMemoryAccess(EarlierInst));
}
@G1 = global i32 zeroinitializer
@G2 = global i32 zeroinitializer
+@G3 = global i32 zeroinitializer
;; Simple load value numbering across non-clobbering store.
; CHECK-LABEL: @test1(
store i32 %sum, i32* @G2
ret void
}
+
+
+;; Check that MemoryPhi optimization and MemoryUse re-optimization
+;; happens during EarlyCSE, enabling more load CSE opportunities.
+; CHECK-LABEL: @test_memphiopt2(
+; CHECK-NOMEMSSA-LABEL: @test_memphiopt2(
+define void @test_memphiopt2(i1 %c, i32* %p) {
+; CHECK-LABEL: entry:
+; CHECK-NOMEMSSA-LABEL: entry:
+entry:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+ %v1 = load i32, i32* @G1
+; CHECK: store
+; CHECK-NOMEMSSA: store
+ store i32 %v1, i32* @G2
+ br i1 %c, label %then, label %end
+
+; CHECK-LABEL: then:
+; CHECK-NOMEMSSA-LABEL: then:
+then:
+; CHECK: load
+; CHECK-NOMEMSSA: load
+ %pv = load i32, i32* %p
+; CHECK-NOT: store
+; CHECK-NOMEMSSA-NOT: store
+ store i32 %pv, i32* %p
+ br label %end
+
+; CHECK-LABEL: end:
+; CHECK-NOMEMSSA-LABEL: end:
+end:
+; CHECK-NOT: load
+; CHECK-NOMEMSSA: load
+ %v2 = load i32, i32* @G1
+ store i32 %v2, i32* @G3
+ ret void
+}