llvm-project/llvm/lib/IR/ReplaceConstant.cpp
Jon Chesterfield 3c76e5f0c8 [amdgpu][nfc] Remove dead code associated with LDS lowering
Pass disabled since approximately D104962 for miscompiling openmp

The functions under ReplaceConstant miscompile phis as noted in D112717 and
have no users in tree other than the disabled pass. It seems likely it has no
users out of tree.

Deletes the test cases associated with the disabled pass as well.

Reviewed By: rampitec

Differential Revision: https://reviews.llvm.org/D147586
2023-04-05 22:24:22 +01:00

103 lines
3.3 KiB
C++

//===- ReplaceConstant.cpp - Replace LLVM constant expression--------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a utility function for replacing LLVM constant
// expressions by instructions.
//
//===----------------------------------------------------------------------===//
#include "llvm/IR/ReplaceConstant.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
namespace llvm {
static bool isExpandableUser(User *U) {
return isa<ConstantExpr>(U) || isa<ConstantAggregate>(U);
}
static Instruction *expandUser(Instruction *InsertPt, Constant *C) {
if (auto *CE = dyn_cast<ConstantExpr>(C)) {
return CE->getAsInstruction(InsertPt);
} else if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) {
Value *V = PoisonValue::get(C->getType());
for (auto [Idx, Op] : enumerate(C->operands()))
V = InsertValueInst::Create(V, Op, Idx, "", InsertPt);
return cast<Instruction>(V);
} else if (isa<ConstantVector>(C)) {
Type *IdxTy = Type::getInt32Ty(C->getContext());
Value *V = PoisonValue::get(C->getType());
for (auto [Idx, Op] : enumerate(C->operands()))
V = InsertElementInst::Create(V, Op, ConstantInt::get(IdxTy, Idx), "",
InsertPt);
return cast<Instruction>(V);
} else {
llvm_unreachable("Not an expandable user");
}
}
bool convertUsersOfConstantsToInstructions(ArrayRef<Constant *> Consts) {
// Find all expandable direct users of Consts.
SmallVector<Constant *> Stack;
for (Constant *C : Consts)
for (User *U : C->users())
if (isExpandableUser(U))
Stack.push_back(cast<Constant>(U));
// Include transitive users.
SetVector<Constant *> ExpandableUsers;
while (!Stack.empty()) {
Constant *C = Stack.pop_back_val();
if (!ExpandableUsers.insert(C))
continue;
for (auto *Nested : C->users())
if (isExpandableUser(Nested))
Stack.push_back(cast<Constant>(Nested));
}
// Find all instructions that use any of the expandable users
SetVector<Instruction *> InstructionWorklist;
for (Constant *C : ExpandableUsers)
for (User *U : C->users())
if (auto *I = dyn_cast<Instruction>(U))
InstructionWorklist.insert(I);
// Replace those expandable operands with instructions
bool Changed = false;
while (!InstructionWorklist.empty()) {
Instruction *I = InstructionWorklist.pop_back_val();
for (Use &U : I->operands()) {
auto *BI = I;
if (auto *Phi = dyn_cast<PHINode>(I)) {
BasicBlock *BB = Phi->getIncomingBlock(U);
BasicBlock::iterator It = BB->getFirstInsertionPt();
assert(It != BB->end() && "Unexpected empty basic block");
BI = &*It;
}
if (auto *C = dyn_cast<Constant>(U.get())) {
if (ExpandableUsers.contains(C)) {
Changed = true;
Instruction *NI = expandUser(BI, C);
InstructionWorklist.insert(NI);
U.set(NI);
}
}
}
}
for (Constant *C : Consts)
C->removeDeadConstantUsers();
return Changed;
}
} // namespace llvm