Index: llvm/lib/Analysis/BasicAliasAnalysis.cpp =================================================================== --- llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -585,13 +585,6 @@ assert(GEPOp->getSourceElementType()->isSized() && "GEP must be sized"); - // Don't attempt to analyze GEPs if index scale is not a compile-time - // constant. - if (isa(GEPOp->getSourceElementType())) { - Decomposed.Base = V; - return Decomposed; - } - unsigned AS = GEPOp->getPointerAddressSpace(); // Walk the indices of the GEP, accumulating them into BaseOff/VarIndices. gep_type_iterator GTI = gep_type_begin(GEPOp); @@ -601,6 +594,7 @@ for (User::const_op_iterator I = GEPOp->op_begin() + 1, E = GEPOp->op_end(); I != E; ++I, ++GTI) { const Value *Index = *I; + TypeSize AllocaTypeSize = DL.getTypeAllocSize(GTI.getIndexedType()); // Compute the (potentially symbolic) offset in bytes for this index. if (StructType *STy = GTI.getStructTypeOrNull()) { // For a struct, add the member offset. @@ -616,12 +610,23 @@ if (const ConstantInt *CIdx = dyn_cast(Index)) { if (CIdx->isZero()) continue; - Decomposed.Offset += - DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize() * - CIdx->getValue().sextOrTrunc(MaxIndexSize); + + // Don't attempt to analyze GEPs if the scalable index is not zero. + if (AllocaTypeSize.isScalable()) { + Decomposed.Base = V; + return Decomposed; + } + + Decomposed.Offset += AllocaTypeSize.getFixedSize() * + CIdx->getValue().sextOrTrunc(MaxIndexSize); continue; } + if (AllocaTypeSize.isScalable()) { + Decomposed.Base = V; + return Decomposed; + } + GepHasConstantOffset = false; // If the integer type is smaller than the index size, it is implicitly @@ -633,8 +638,7 @@ CastedValue(Index, 0, SExtBits, TruncBits), DL, 0, AC, DT); // Scale by the type size. - unsigned TypeSize = - DL.getTypeAllocSize(GTI.getIndexedType()).getFixedSize(); + unsigned TypeSize = AllocaTypeSize.getFixedSize(); LE = LE.mul(APInt(IndexSize, TypeSize), GEPOp->isInBounds()); Decomposed.Offset += LE.Offset.sext(MaxIndexSize); APInt Scale = LE.Scale.sext(MaxIndexSize); Index: llvm/test/Transforms/GVN/vscale.ll =================================================================== --- llvm/test/Transforms/GVN/vscale.ll +++ llvm/test/Transforms/GVN/vscale.ll @@ -46,15 +46,12 @@ ret %add } -; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias. +; BasicAA return MayAlias for %gep1,%gep2, could improve as MustAlias. define i32 @load_clobber_load_gep1(* %p) { ; CHECK-LABEL: @load_clobber_load_gep1( ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr , * [[P:%.*]], i64 0, i64 1 ; CHECK-NEXT: [[LOAD1:%.*]] = load i32, i32* [[GEP1]], align 4 -; CHECK-NEXT: [[P2:%.*]] = bitcast * [[P]] to i32* -; CHECK-NEXT: [[GEP2:%.*]] = getelementptr i32, i32* [[P2]], i64 1 -; CHECK-NEXT: [[LOAD2:%.*]] = load i32, i32* [[GEP2]], align 4 -; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD2]] +; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LOAD1]], [[LOAD1]] ; CHECK-NEXT: ret i32 [[ADD]] ; %gep1 = getelementptr , * %p, i64 0, i64 1 @@ -164,7 +161,7 @@ define i32 @store_clobber_load() { ; CHECK-LABEL: @store_clobber_load( -; CHECK-NEXT: [[ALLOC:%.*]] = alloca +; CHECK-NEXT: [[ALLOC:%.*]] = alloca , align 16 ; CHECK-NEXT: store undef, * [[ALLOC]], align 16 ; CHECK-NEXT: [[PTR:%.*]] = getelementptr , * [[ALLOC]], i32 0, i32 1 ; CHECK-NEXT: [[LOAD:%.*]] = load i32, i32* [[PTR]], align 4 @@ -230,7 +227,7 @@ define * @load_from_alloc_replaced_with_undef() { ; CHECK-LABEL: @load_from_alloc_replaced_with_undef( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[A:%.*]] = alloca +; CHECK-NEXT: [[A:%.*]] = alloca , align 16 ; CHECK-NEXT: br i1 undef, label [[IF_END:%.*]], label [[IF_THEN:%.*]] ; CHECK: if.then: ; CHECK-NEXT: store zeroinitializer, * [[A]], align 16 @@ -282,7 +279,7 @@ } ; TODO: BasicAA return MayAlias for %gep1,%gep2, could improve as NoAlias. -define void @redundant_load_elimination_2(i1 %c, * %p, i32* %q, %v) { +define void @redundant_load_elimination_2(i1 %c, * %p, i32* %q) { ; CHECK-LABEL: @redundant_load_elimination_2( ; CHECK-NEXT: entry: ; CHECK-NEXT: [[GEP1:%.*]] = getelementptr , * [[P:%.*]], i64 1, i64 1 @@ -313,6 +310,36 @@ ret void } +define void @redundant_load_elimination_zero_index(i1 %c, * %p, i32* %q) { +; CHECK-LABEL: @redundant_load_elimination_zero_index( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[GEP1:%.*]] = getelementptr , * [[P:%.*]], i64 0, i64 1 +; CHECK-NEXT: store i32 0, i32* [[GEP1]], align 4 +; CHECK-NEXT: [[GEP2:%.*]] = getelementptr , * [[P]], i64 0, i64 0 +; CHECK-NEXT: store i32 1, i32* [[GEP2]], align 4 +; CHECK-NEXT: br i1 [[C:%.*]], label [[IF_ELSE:%.*]], label [[IF_THEN:%.*]] +; CHECK: if.then: +; CHECK-NEXT: store i32 0, i32* [[Q:%.*]], align 4 +; CHECK-NEXT: ret void +; CHECK: if.else: +; CHECK-NEXT: ret void +; +entry: + %gep1 = getelementptr , * %p, i64 0, i64 1 + store i32 0, i32* %gep1 + %gep2 = getelementptr , * %p, i64 0, i64 0 + store i32 1, i32* %gep2 + br i1 %c, label %if.else, label %if.then + +if.then: + %t = load i32, i32* %gep1 ; <- load could be eliminated + store i32 %t, i32* %q + ret void + +if.else: + ret void +} + ; TODO: load in if.then could have been eliminated define void @missing_load_elimination(i1 %c, * %p, * %q, %v) { ; CHECK-LABEL: @missing_load_elimination(