[PATCH] D22269: [SCCP] Replace structs with constants if all the lattice values are constant
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 12 10:44:57 PDT 2016
davide created this revision.
davide added a reviewer: eli.friedman.
davide added a subscriber: llvm-commits.
I originally started working on adding support for vectors `insertelement` and friends than I realized we could re-use the code we use for handling structs for the purpose.
So, I decided to struct support first and put the rewrite of http://reviews.llvm.org/D22186 on hold.
This patch only works for `SCCP` but it shouldn't be hard to port to the interprocedural version of this pass if we agree this is the right way of handling this case.
http://reviews.llvm.org/D22269
Files:
lib/Transforms/Scalar/SCCP.cpp
test/Transforms/SCCP/constant-struct.ll
Index: test/Transforms/SCCP/constant-struct.ll
===================================================================
--- /dev/null
+++ test/Transforms/SCCP/constant-struct.ll
@@ -0,0 +1,32 @@
+; Test that constant structs are folded.
+; RUN: opt %s -sccp -S | FileCheck %s
+
+define internal {i64} @struct1() {
+ %a = insertvalue {i64} undef, i64 24, 0
+ ret {i64} %a
+}
+
+; CHECK: define internal { i64 } @struct1() {
+; CHECK-NEXT: ret { i64 } { i64 24 }
+; CHECK-NEXT: }
+
+define internal {i64, i64} @struct2() {
+ %a = insertvalue {i64, i64} undef, i64 24, 0
+ ret {i64, i64} %a
+}
+
+; CHECK: define internal { i64, i64 } @struct2() {
+; CHECK-NEXT: ret { i64, i64 } { i64 24, i64 undef }
+; CHECK-NEXT: }
+
+define internal {i64, i64, i64} @struct3(i64 %x) {
+ %a = insertvalue {i64, i64, i64} undef, i64 24, 0
+ %b = insertvalue {i64, i64, i64} %a, i64 36, 1
+ %c = insertvalue {i64, i64, i64} %b, i64 %x, 2
+ ret {i64, i64, i64} %c
+}
+
+; CHECK: define internal { i64, i64, i64 } @struct3(i64 %x) {
+; CHECK-NEXT: %c = insertvalue { i64, i64, i64 } { i64 24, i64 36, i64 undef }, i64 %x, 2
+; CHECK-NEXT: ret { i64, i64, i64 } %c
+; CHECK-NEXT: }
Index: lib/Transforms/Scalar/SCCP.cpp
===================================================================
--- lib/Transforms/Scalar/SCCP.cpp
+++ lib/Transforms/Scalar/SCCP.cpp
@@ -270,6 +270,18 @@
return BBExecutable.count(BB);
}
+ std::vector<LatticeVal> getStructLatticeValueFor(Value *V) const {
+ std::vector<LatticeVal> StructValues;
+ StructType *STy = dyn_cast<StructType>(V->getType());
+ assert(STy && "getStructLatticeValueFor() can be called only on structs");
+ for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
+ auto I = StructValueState.find(std::make_pair(V, i));
+ assert(I != StructValueState.end() && "Value not in valuemap!");
+ StructValues.push_back(I->second);
+ }
+ return StructValues;
+ }
+
LatticeVal getLatticeValueFor(Value *V) const {
DenseMap<Value*, LatticeVal>::const_iterator I = ValueState.find(V);
assert(I != ValueState.end() && "V is not in valuemap!");
@@ -1545,16 +1557,30 @@
if (Inst->getType()->isVoidTy() || isa<TerminatorInst>(Inst))
continue;
- // TODO: Reconstruct structs from their elements.
- if (Inst->getType()->isStructTy())
- continue;
-
- LatticeVal IV = Solver.getLatticeValueFor(Inst);
- if (IV.isOverdefined())
- continue;
+ Constant *Const = nullptr;
+ if (Inst->getType()->isStructTy()) {
+ std::vector<LatticeVal> IVs = Solver.getStructLatticeValueFor(Inst);
+ if (std::any_of(IVs.begin(), IVs.end(),
+ [](LatticeVal &LV) { return LV.isOverdefined(); }))
+ continue;
+ std::vector<Constant *> ConstVals;
+ StructType *ST = dyn_cast<StructType>(Inst->getType());
+ for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) {
+ LatticeVal V = IVs[i];
+ ConstVals.push_back(V.isConstant()
+ ? V.getConstant()
+ : UndefValue::get(ST->getElementType(i)));
+ }
+ Const = ConstantStruct::get(ST, ConstVals);
+ } else {
+ LatticeVal IV = Solver.getLatticeValueFor(Inst);
+ if (IV.isOverdefined())
+ continue;
- Constant *Const = IV.isConstant()
- ? IV.getConstant() : UndefValue::get(Inst->getType());
+ Const = IV.isConstant() ? IV.getConstant()
+ : UndefValue::get(Inst->getType());
+ }
+ assert(Const && "Constant is nullptr here!");
DEBUG(dbgs() << " Constant: " << *Const << " = " << *Inst << '\n');
// Replaces all of the uses of a variable with uses of the constant.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D22269.63693.patch
Type: text/x-patch
Size: 3802 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160712/ef6f304d/attachment.bin>
More information about the llvm-commits
mailing list