Index: llvm/lib/Transforms/IPO/Attributor.cpp =================================================================== --- llvm/lib/Transforms/IPO/Attributor.cpp +++ llvm/lib/Transforms/IPO/Attributor.cpp @@ -38,6 +38,8 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" +#include + #include using namespace llvm; @@ -1968,21 +1970,36 @@ struct AAUndefinedBehaviorImpl : public AAUndefinedBehavior { AAUndefinedBehaviorImpl(const IRPosition &IRP) : AAUndefinedBehavior(IRP) {} + std::unordered_set noUBLoads; + /// See AbstractAttribute::initialize(...). void initialize(Attributor &A) override { AAUndefinedBehavior::initialize(A); - - auto HandleLoadInstruction = [&](Instruction &I) { - // TODO: Do something for every load instruction... - return true; - }; - A.checkForAllInstructions(HandleLoadInstruction, *this, - {Instruction::Load}); } /// See AbstractAttribute::updateImpl(...). ChangeStatus updateImpl(Attributor &A) override { - return indicatePessimisticFixpoint(); + size_t prevSize = noUBLoads.size(); + + auto CantCauseUB = [&](Instruction &Iref) { + Instruction *I = &Iref; + // If this load instruction is not one of the instructions + // that are already assumed to cause UB. + if (noUBLoads.find(I) == noUBLoads.end()) { + // Find whether it can cause UB by checking if the pointer + // is null or undef. + bool canCauseUB; + if (!canCauseUB) { + noUBLoads.insert(I); + } + } + return true; + }; + A.checkForAllInstructions(CantCauseUB, *this, {Instruction::Load}); + if (prevSize != noUBLoads.size()) { + return ChangeStatus::CHANGED; + } + return ChangeStatus::UNCHANGED; } /// See AbstractAttribute::getAsStr()