diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5852,6 +5852,54 @@ return ::SimplifyFreezeInst(Op0, Q); } +static Constant *ConstructLoadOperandConstant(Value *Op) { + if (auto *C = dyn_cast(Op)) + return C; + + if (auto *BC = dyn_cast(Op)) { + if (auto *C = ConstructLoadOperandConstant(BC->getOperand(0))) { + return ConstantExpr::getBitCast(C, BC->getType()); + } + return nullptr; + } + if (auto *GEP = dyn_cast(Op)) { + if (auto *C = ConstructLoadOperandConstant(GEP->getPointerOperand())) { + SmallVector Idxs; + for (unsigned I = 1, E = GEP->getNumOperands(); I != E; ++I) { + if (auto *Idx = dyn_cast(GEP->getOperand(I))) + Idxs.push_back(Idx); + else + return nullptr; + } + return ConstantExpr::getGetElementPtr(GEP->getSourceElementType(), C, + Idxs, GEP->isInBounds(), + GEP->getInRangeIndex()); + } + return nullptr; + } + if (auto *II = dyn_cast(Op)) { + if (II->getIntrinsicID() == Intrinsic::strip_invariant_group || + II->getIntrinsicID() == Intrinsic::launder_invariant_group) { + if (auto *C = ConstructLoadOperandConstant(II->getOperand(0))) { + return ConstantExpr::getBitCast(C, II->getType()); + } + } + return nullptr; + } + return nullptr; +} + +static Value *SimplifyLoadInst(LoadInst *LI, const SimplifyQuery &Q) { + if (auto *C = dyn_cast(LI->getPointerOperand())) + return ConstantFoldLoadFromConstPtr(C, LI->getType(), Q.DL); + + if (auto *C = dyn_cast_or_null( + ConstructLoadOperandConstant(LI->getPointerOperand()))) + return ConstantFoldLoadFromConstPtr(C, LI->getType(), Q.DL); + + return nullptr; +} + /// See if we can compute a simplified version of this instruction. /// If not, this returns null. @@ -6008,6 +6056,9 @@ // No simplifications for Alloca and it can't be constant folded. Result = nullptr; break; + case Instruction::Load: + Result = SimplifyLoadInst(cast(I), Q); + break; } /// If called on unreachable code, the above logic may report that the diff --git a/llvm/test/Transforms/InstSimplify/invariant.group-load.ll b/llvm/test/Transforms/InstSimplify/invariant.group-load.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/invariant.group-load.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -passes=instsimplify -S < %s | FileCheck %s + +@A = linkonce_odr hidden constant { i64, i64 } { i64 2, i64 3 } + +declare i8* @llvm.strip.invariant.group.p0i8(i8* %p) + +define i64 @f() { +; CHECK-LABEL: @f( +; CHECK-NEXT: ret i64 3 +; + %p = bitcast { i64, i64 }* @A to i8* + %a = call i8* @llvm.strip.invariant.group.p0i8(i8* %p) + %b = getelementptr i8, i8* %a, i32 8 + %c = bitcast i8* %b to i64* + %d = load i64, i64* %c + ret i64 %d +}