[llvm] r314362 - Check for overflows when calculating the offset in GetGEPCost.

Justin Lebar via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 27 16:16:56 PDT 2017


Author: jlebar
Date: Wed Sep 27 16:16:56 2017
New Revision: 314362

URL: http://llvm.org/viewvc/llvm-project?rev=314362&view=rev
Log:
Check for overflows when calculating the offset in GetGEPCost.

Summary:
This avoids C++ UB if the GEP is weird and the calculation overflows
int64_t, and it's also observable in the cost model's results.

Such GEPs are almost surely not valid pointers, but LLVM nonetheless
generates them sometimes.

Reviewers: sanjoy

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D38337

Modified:
    llvm/trunk/include/llvm/Analysis/TargetTransformInfoImpl.h
    llvm/trunk/test/Analysis/CostModel/X86/gep.ll

Modified: llvm/trunk/include/llvm/Analysis/TargetTransformInfoImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/TargetTransformInfoImpl.h?rev=314362&r1=314361&r2=314362&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/TargetTransformInfoImpl.h (original)
+++ llvm/trunk/include/llvm/Analysis/TargetTransformInfoImpl.h Wed Sep 27 16:16:56 2017
@@ -674,7 +674,9 @@ public:
       BaseGV = dyn_cast<GlobalValue>(Ptr->stripPointerCasts());
     }
     bool HasBaseReg = (BaseGV == nullptr);
-    int64_t BaseOffset = 0;
+
+    auto PtrSizeBits = DL.getPointerTypeSizeInBits(Ptr->getType());
+    APInt BaseOffset(PtrSizeBits, 0);
     int64_t Scale = 0;
 
     auto GTI = gep_type_begin(PointeeType, Operands);
@@ -700,9 +702,10 @@ public:
         BaseOffset += DL.getStructLayout(STy)->getElementOffset(Field);
       } else {
         int64_t ElementSize = DL.getTypeAllocSize(GTI.getIndexedType());
-        if (ConstIdx)
-          BaseOffset += ConstIdx->getSExtValue() * ElementSize;
-        else {
+        if (ConstIdx) {
+          BaseOffset +=
+              ConstIdx->getValue().sextOrTrunc(PtrSizeBits) * ElementSize;
+        } else {
           // Needs scale register.
           if (Scale != 0)
             // No addressing mode takes two scale registers.
@@ -716,8 +719,9 @@ public:
     unsigned AS =
         (Ptr == nullptr ? 0 : Ptr->getType()->getPointerAddressSpace());
     if (static_cast<T *>(this)->isLegalAddressingMode(
-            TargetType, const_cast<GlobalValue *>(BaseGV), BaseOffset,
-            HasBaseReg, Scale, AS))
+            TargetType, const_cast<GlobalValue *>(BaseGV),
+            static_cast<int64_t>(BaseOffset.getLimitedValue()), HasBaseReg,
+            Scale, AS))
       return TTI::TCC_Free;
     return TTI::TCC_Basic;
   }

Modified: llvm/trunk/test/Analysis/CostModel/X86/gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/CostModel/X86/gep.ll?rev=314362&r1=314361&r2=314362&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/CostModel/X86/gep.ll (original)
+++ llvm/trunk/test/Analysis/CostModel/X86/gep.ll Wed Sep 27 16:16:56 2017
@@ -35,6 +35,17 @@ define void @test_geps() {
 ;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds <4 x double>, <4 x double>*
   %a12 = getelementptr inbounds <4 x double>, <4 x double>* undef, i32 0
 
+  ; Check that we handle outlandishly large GEPs properly.  This is unlikely to
+  ; be a valid pointer, but LLVM still generates GEPs like this sometimes in
+  ; dead code.
+  ;
+  ; This GEP has index INT64_MAX, which is cost 1.
+;CHECK: cost of 1 for instruction: {{.*}} getelementptr inbounds i8, i8*
+  %giant_gep0 = getelementptr inbounds i8, i8* undef, i64 9223372036854775807
+
+  ; This GEP index wraps around to -1, which is cost 0.
+;CHECK: cost of 0 for instruction: {{.*}} getelementptr inbounds i8, i8*
+  %giant_gep1 = getelementptr inbounds i8, i8* undef, i128 295147905179352825855
 
   ret void
 }




More information about the llvm-commits mailing list