Index: llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -754,8 +754,10 @@ explicit BDVState(Value *OriginalValue) : OriginalValue(OriginalValue) {} - explicit BDVState(Value *OriginalValue, StatusTy Status, Value *BaseValue = nullptr) - : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue) { + explicit BDVState(Value *OriginalValue, StatusTy Status, + Value *BaseValue = nullptr, bool IsDerived = true) + : OriginalValue(OriginalValue), Status(Status), BaseValue(BaseValue), + IsDerived(IsDerived) { assert(Status != Base || BaseValue); } @@ -766,6 +768,10 @@ bool isBase() const { return getStatus() == Base; } bool isUnknown() const { return getStatus() == Unknown; } bool isConflict() const { return getStatus() == Conflict; } + bool isDerived() const { return IsDerived; } + void setIsDerived(bool IsDerived) { + this->IsDerived = IsDerived; + } // Values of type BDVState form a lattice, and this function implements the // meet @@ -774,6 +780,7 @@ auto markConflict = [&]() { Status = BDVState::Conflict; BaseValue = nullptr; + IsDerived = true; }; // Conflict is a final state. if (isConflict()) @@ -782,6 +789,7 @@ if (isUnknown()) { Status = Other.getStatus(); BaseValue = Other.getBaseValue(); + IsDerived = Other.isDerived(); return; } // We are base. @@ -797,12 +805,13 @@ // If bases are different - Conflict. if (getBaseValue() != Other.getBaseValue()) return markConflict(); - // We are identical, do nothing. + // We have the same bases. If the other is derived, so we are. + IsDerived |= Other.isDerived(); } bool operator==(const BDVState &Other) const { return OriginalValue == Other.OriginalValue && BaseValue == Other.BaseValue && - Status == Other.Status; + Status == Other.Status && IsDerived == Other.IsDerived; } bool operator!=(const BDVState &other) const { return !(*this == other); } @@ -826,14 +835,16 @@ break; } OS << " (base " << getBaseValue() << " - " - << (getBaseValue() ? getBaseValue()->getName() : "nullptr") << ")" - << " for " << OriginalValue->getName() << ":"; + << (getBaseValue() ? getBaseValue()->getName() : "nullptr") + << ", is derived = " << isDerived() << ")" + << " for " << OriginalValue->getName() << ":"; } private: AssertingVH OriginalValue; // instruction this state corresponds to StatusTy Status = Unknown; AssertingVH BaseValue = nullptr; // Non-null only if Status == Base. + bool IsDerived = true; }; } // end anonymous namespace @@ -1011,10 +1022,12 @@ // base state for known bases and expect to find a cached state otherwise. auto GetStateForBDV = [&](BaseDefiningValueResult &BaseValue, Value *Input) { auto I = States.find(BaseValue); - if (I != States.end()) - return I->second; - assert(areBothVectorOrScalar(BaseValue.getBDV(), Input)); - return BDVState(BaseValue.getBDV(), BDVState::Base, BaseValue.getBDV()); + if (I == States.end() || BaseValue.isKnownBase()) { + assert(areBothVectorOrScalar(BaseValue.getBDV(), Input)); + return BDVState(BaseValue.getBDV(), BDVState::Base, BaseValue.getBDV(), + /*IsDerived=*/false); + } + return I->second; }; bool Progress = true; @@ -1042,6 +1055,10 @@ auto BaseOrBDV = findBaseOrBDV(Op, Cache); Value *BDV = BaseOrBDV.getBDV(); auto OpState = GetStateForBDV(BaseOrBDV, Op); + // If the operand is not the same as its BDV the state should be + // derived. + if (Op->stripPointerCasts() != BDV) + OpState.setIsDerived(true); NewState.meet(OpState); }); @@ -1293,6 +1310,8 @@ auto *BDV = Pair.first.getBDV(); Value *Base = Pair.second.getBaseValue(); assert(BDV && Base); + if (!Pair.second.isDerived() && !isOriginalBaseResult(BDV)) + Base = Pair.second.getOriginalValue(); // Only values that do not have known bases or those that have differing // type (scalar versus vector) from a possible known base should be in the // lattice. Index: llvm/test/Transforms/RewriteStatepointsForGC/single-base.ll =================================================================== --- llvm/test/Transforms/RewriteStatepointsForGC/single-base.ll +++ llvm/test/Transforms/RewriteStatepointsForGC/single-base.ll @@ -24,9 +24,8 @@ ; CHECK-NEXT: br i1 [[C3]], label [[LOOP]], label [[EXIT]] ; CHECK: exit: ; CHECK-NEXT: [[MERGE:%.*]] = phi i8 addrspace(1)* [ [[B5]], [[LOOP]] ], [ [[B6]], [[INNER_LOOP_LATCH]] ] -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[MERGE]], i8 addrspace(1)* [[B1]]) ] -; CHECK-NEXT: [[MERGE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[MERGE]]) ] +; CHECK-NEXT: [[MERGE_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[MERGE_RELOCATED]] ; entry: @@ -62,9 +61,8 @@ ; CHECK-NEXT: [[C1:%.*]] = call i1 @runtime_value() ; CHECK-NEXT: br i1 [[C1]], label [[LOOP]], label [[EXIT:%.*]] ; CHECK: exit: -; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]], i8 addrspace(1)* [[B1]]) ] -; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 0) -; CHECK-NEXT: [[B1_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 1, i32 1) +; CHECK-NEXT: [[STATEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0) [ "deopt"(), "gc-live"(i8 addrspace(1)* [[B6]]) ] +; CHECK-NEXT: [[B6_RELOCATED:%.*]] = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token [[STATEPOINT_TOKEN]], i32 0, i32 0) ; CHECK-NEXT: ret i8 addrspace(1)* [[B6_RELOCATED]] ; entry: