[PATCH] D101103: [InstSimplify] Treat invariant group insts as bitcasts for load operands
Roman Lebedev via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 27 00:56:58 PDT 2021
lebedev.ri added a comment.
I think the recursion is unfortunate there. How about something like
static Constant *ConstructLoadOperandConstant(Value *Op) {
SmallVector<Value*, 16> Worklist;
OpStack.emplace_back(Op);
for(int I = 0; I != OpStack.size(); ++I) {
Value* Op = OpStack.back();
if (isa<Constant>(Op))
break; // YAY!
if (auto *BC = dyn_cast<BitCastOperator>(Op))
OpStack.emplace_back(BC->getOperand(0)); // Recurse.
if (auto *GEP = dyn_cast<GEPOperator>(Op)) {
if (all_of(ArrayRef<Value*>(GEP->operands()).drop_front(),
[](Value*Op) { return isa<Constant>(Op); }))
OpStack.emplace_back(GEP->getOperand(0)); // Recurse.
}
if (auto *II = dyn_cast<IntrinsicInst>(Op)) {
if (II->getIntrinsicID() == Intrinsic::strip_invariant_group ||
II->getIntrinsicID() == Intrinsic::launder_invariant_group)
OpStack.emplace_back(II->getOperand(0)); // Recurse.
}
return nullptr; // Can't look past this instruction. Give up.
}
// Alright! Reconstruct this chain as constant expressions.
Constant* NewOp = cast<Constant>(Worklist.pop_back_val());
while(!OpStack.empty()) {
Value* Op = OpStack.pop_back_val();
if (isa<BitCastOperator>(Op))
NewOp = ConstantExpr::getBitCast(NewOp, Op->getType());
if (auto *GEP = dyn_cast<GEPOperator>(Op)) {
SmallVector<Constant *> Idxs;
Idxs.reserve(GEP->getNumOperands() - 1);
for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I)
Idxs.push_back(cast<Constant>(GEP->getOperand(I));
return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), NewOp,
Idxs, GEP->isInBounds(),
GEP->getInRangeIndex());
}
if (auto *II = dyn_cast<IntrinsicInst>(Op)) {
if (II->getIntrinsicID() == Intrinsic::strip_invariant_group ||
II->getIntrinsicID() == Intrinsic::launder_invariant_group)
NewOp = ConstantExpr::getBitCast(NewOp, Op->getType());
}
llvm_unreachable("Instruction handled in first loop but not here?");
}
}
return NewOp;
================
Comment at: llvm/lib/Analysis/InstructionSimplify.cpp:5855
+static Constant *ConstructLoadOperandConstant(Value *Op) {
+ if (auto *C = dyn_cast<Constant>(Op))
----------------
Given load from \p Op, see if we can peel off certain pointer adjustments,
that are no-op for the purpose of the performing the load,
in the hope of eventually discovering that we are
actually loading from a constant.
================
Comment at: llvm/lib/Analysis/InstructionSimplify.cpp:5893-5894
+static Value *SimplifyLoadInst(LoadInst *LI, const SimplifyQuery &Q) {
+ if (auto *C = dyn_cast<Constant>(LI->getPointerOperand()))
+ return ConstantFoldLoadFromConstPtr(C, LI->getType(), Q.DL);
+
----------------
As per D33619. and the default of the switch in `SimplifyInstruction()`,
we'll no longer call `ConstantFoldInstruction()`, but just the `ConstantFoldLoadFromConstPtr()`.
Will we loose anything important because of that?
I would guess that iff we actually want to change that, perhaps it should be done afterwards,
and this should just continue to use `ConstantFoldInstruction()`?
================
Comment at: llvm/test/Transforms/InstSimplify/invariant.group-load.ll:2
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=instsimplify -S < %s | FileCheck %s
+
----------------
I'd like to see a bit more tests.
For example, this really needs negative tests.
What should happen if the `@A` isn't a `constant`?
One test with some pattern we can't handle would be good (non-constant gep indexes e.g.)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D101103/new/
https://reviews.llvm.org/D101103
More information about the llvm-commits
mailing list