forked from OSchip/llvm-project
				
			teach SCEV that the scale and addition of an inbounds gep don't NSW.
This fixes a FIXME in scev-aa.ll (allowing a new no-alias result) and generally makes things more precise. llvm-svn: 125449
This commit is contained in:
		
							parent
							
								
									2b3c5538fa
								
							
						
					
					
						commit
						4f23f2be15
					
				| 
						 | 
					@ -2870,6 +2870,7 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
 | 
				
			||||||
  // Add expression, because the Instruction may be guarded by control flow
 | 
					  // Add expression, because the Instruction may be guarded by control flow
 | 
				
			||||||
  // and the no-overflow bits may not be valid for the expression in any
 | 
					  // and the no-overflow bits may not be valid for the expression in any
 | 
				
			||||||
  // context.
 | 
					  // context.
 | 
				
			||||||
 | 
					  bool isInBounds = GEP->isInBounds();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType());
 | 
					  const Type *IntPtrTy = getEffectiveSCEVType(GEP->getType());
 | 
				
			||||||
  Value *Base = GEP->getOperand(0);
 | 
					  Value *Base = GEP->getOperand(0);
 | 
				
			||||||
| 
						 | 
					@ -2898,7 +2899,8 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
 | 
				
			||||||
      IndexS = getTruncateOrSignExtend(IndexS, IntPtrTy);
 | 
					      IndexS = getTruncateOrSignExtend(IndexS, IntPtrTy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Multiply the index by the element size to compute the element offset.
 | 
					      // Multiply the index by the element size to compute the element offset.
 | 
				
			||||||
      const SCEV *LocalOffset = getMulExpr(IndexS, ElementSize);
 | 
					      const SCEV *LocalOffset = getMulExpr(IndexS, ElementSize, /*NUW*/ false,
 | 
				
			||||||
 | 
					                                           /*NSW*/ isInBounds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      // Add the element offset to the running total offset.
 | 
					      // Add the element offset to the running total offset.
 | 
				
			||||||
      TotalOffset = getAddExpr(TotalOffset, LocalOffset);
 | 
					      TotalOffset = getAddExpr(TotalOffset, LocalOffset);
 | 
				
			||||||
| 
						 | 
					@ -2909,7 +2911,8 @@ const SCEV *ScalarEvolution::createNodeForGEP(GEPOperator *GEP) {
 | 
				
			||||||
  const SCEV *BaseS = getSCEV(Base);
 | 
					  const SCEV *BaseS = getSCEV(Base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Add the total offset from all the GEP indices to the base.
 | 
					  // Add the total offset from all the GEP indices to the base.
 | 
				
			||||||
  return getAddExpr(BaseS, TotalOffset);
 | 
					  return getAddExpr(BaseS, TotalOffset, /*NUW*/ false,
 | 
				
			||||||
 | 
					                    /*NSW*/ isInBounds);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
 | 
					/// GetMinTrailingZeros - Determine the minimum number of zero bits that S is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -76,3 +76,31 @@ for.cond.for.end_crit_edge.i.i:                   ; preds = %for.body.i.i
 | 
				
			||||||
_ZSt4fillIPiiEvT_S1_RKT0_.exit:                   ; preds = %entry, %for.cond.for.end_crit_edge.i.i
 | 
					_ZSt4fillIPiiEvT_S1_RKT0_.exit:                   ; preds = %entry, %for.cond.for.end_crit_edge.i.i
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					; Various checks for inbounds geps.
 | 
				
			||||||
 | 
					define void @test3(i32* %begin, i32* %end) nounwind ssp {
 | 
				
			||||||
 | 
					entry:
 | 
				
			||||||
 | 
					  %cmp7.i.i = icmp eq i32* %begin, %end
 | 
				
			||||||
 | 
					  br i1 %cmp7.i.i, label %_ZSt4fillIPiiEvT_S1_RKT0_.exit, label %for.body.i.i
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for.body.i.i:                                     ; preds = %entry, %for.body.i.i
 | 
				
			||||||
 | 
					  %indvar.i.i = phi i64 [ %tmp, %for.body.i.i ], [ 0, %entry ]
 | 
				
			||||||
 | 
					; CHECK: %indvar.i.i
 | 
				
			||||||
 | 
					; CHECK: {0,+,1}<nuw><nsw><%for.body.i.i>
 | 
				
			||||||
 | 
					  %tmp = add nsw i64 %indvar.i.i, 1
 | 
				
			||||||
 | 
					; CHECK: %tmp = 
 | 
				
			||||||
 | 
					; CHECK: {1,+,1}<nuw><nsw><%for.body.i.i>
 | 
				
			||||||
 | 
					  %ptrincdec.i.i = getelementptr inbounds i32* %begin, i64 %tmp
 | 
				
			||||||
 | 
					; CHECK: %ptrincdec.i.i =
 | 
				
			||||||
 | 
					; CHECK: {(4 + %begin),+,4}<nsw><%for.body.i.i>
 | 
				
			||||||
 | 
					  %__first.addr.08.i.i = getelementptr inbounds i32* %begin, i64 %indvar.i.i
 | 
				
			||||||
 | 
					; CHECK: %__first.addr.08.i.i
 | 
				
			||||||
 | 
					; CHECK: {%begin,+,4}<nsw><%for.body.i.i>
 | 
				
			||||||
 | 
					  store i32 0, i32* %__first.addr.08.i.i, align 4
 | 
				
			||||||
 | 
					  %cmp.i.i = icmp eq i32* %ptrincdec.i.i, %end
 | 
				
			||||||
 | 
					  br i1 %cmp.i.i, label %_ZSt4fillIPiiEvT_S1_RKT0_.exit, label %for.body.i.i
 | 
				
			||||||
 | 
					; CHECK: Loop %for.body.i.i: Unpredictable backedge-taken count. 
 | 
				
			||||||
 | 
					; CHECK: Loop %for.body.i.i: Unpredictable max backedge-taken count.
 | 
				
			||||||
 | 
					_ZSt4fillIPiiEvT_S1_RKT0_.exit:                   ; preds = %for.body.i.i, %entry
 | 
				
			||||||
 | 
					  ret void
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -190,9 +190,8 @@ define void @bar() {
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
; TODO: This is theoretically provable to be NoAlias.
 | 
					 | 
				
			||||||
; CHECK: Function: nonnegative: 2 pointers, 0 call sites
 | 
					; CHECK: Function: nonnegative: 2 pointers, 0 call sites
 | 
				
			||||||
; CHECK: MayAlias:  i64* %arrayidx, i64* %p
 | 
					; CHECK: NoAlias:  i64* %arrayidx, i64* %p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
define void @nonnegative(i64* %p) nounwind {
 | 
					define void @nonnegative(i64* %p) nounwind {
 | 
				
			||||||
entry:
 | 
					entry:
 | 
				
			||||||
| 
						 | 
					@ -211,6 +210,6 @@ for.end:                                          ; preds = %for.body, %entry
 | 
				
			||||||
  ret void
 | 
					  ret void
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
; CHECK: 13 no alias responses
 | 
					; CHECK: 14 no alias responses
 | 
				
			||||||
; CHECK: 27 may alias responses
 | 
					; CHECK: 26 may alias responses
 | 
				
			||||||
; CHECK: 18 must alias responses
 | 
					; CHECK: 18 must alias responses
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue