[llvm] r275208 - [SCCP] Constant fold structs if all the lattice value are constant.
Davide Italiano via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 12 12:54:20 PDT 2016
Author: davide
Date: Tue Jul 12 14:54:19 2016
New Revision: 275208
URL: http://llvm.org/viewvc/llvm-project?rev=275208&view=rev
Log:
[SCCP] Constant fold structs if all the lattice value are constant.
Differential Revision: http://reviews.llvm.org/D22269
Added:
llvm/trunk/test/Transforms/SCCP/constant-struct.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/SCCP.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SCCP.cpp?rev=275208&r1=275207&r2=275208&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SCCP.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SCCP.cpp Tue Jul 12 14:54:19 2016
@@ -270,6 +270,18 @@ public:
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 @@ static bool runSCCP(Function &F, const D
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.
Added: llvm/trunk/test/Transforms/SCCP/constant-struct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SCCP/constant-struct.ll?rev=275208&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SCCP/constant-struct.ll (added)
+++ llvm/trunk/test/Transforms/SCCP/constant-struct.ll Tue Jul 12 14:54:19 2016
@@ -0,0 +1,72 @@
+; 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: }
+
+; Test(s) for overdefined values.
+define internal {i64, i32} @struct4(i32 %x) {
+ %a = insertvalue {i64, i32} {i64 12, i32 24}, i32 %x, 1
+ ret {i64, i32} %a
+}
+
+; CHECK: define internal { i64, i32 } @struct4(i32 %x) {
+; CHECK-NEXT: %a = insertvalue { i64, i32 } { i64 12, i32 24 }, i32 %x, 1
+; CHECK-NEXT: ret { i64, i32 } %a
+; CHECK-NEXT: }
+
+define internal {i32} @struct5(i32 %x) {
+ %a = insertvalue {i32} undef, i32 %x, 0
+ ret {i32} %a
+}
+
+; CHECK: define internal { i32 } @struct5(i32 %x) {
+; CHECK-NEXT: %a = insertvalue { i32 } undef, i32 %x, 0
+; CHECK-NEXT: ret { i32 } %a
+; CHECK-NEXT: }
+
+
+define internal {i32} @struct6({i32} %x) {
+ %a = insertvalue {i32} %x, i32 12, 0
+ ret {i32} %a
+}
+
+; CHECK: define internal { i32 } @struct6({ i32 } %x) {
+; CHECK-NEXT: ret { i32 } { i32 12 }
+; CHECK-NEXT: }
+
+define internal {i16} @struct7() {
+ %a = insertvalue {i16} {i16 4}, i16 7, 0
+ ret {i16} %a
+}
+
+; CHECK: define internal { i16 } @struct7() {
+; CHECK-NEXT: ret { i16 } { i16 7 }
+; CHECK-NEXT: }
More information about the llvm-commits
mailing list