[llvm] r272969 - [safestack] Sink unsafe address computation to each use.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 16 15:34:04 PDT 2016


Author: eugenis
Date: Thu Jun 16 17:34:04 2016
New Revision: 272969

URL: http://llvm.org/viewvc/llvm-project?rev=272969&view=rev
Log:
[safestack] Sink unsafe address computation to each use.

This is a fix for PR27844.
When replacing uses of unsafe allocas, emit the new location
immediately after each use. Without this, the pointer stays live from
the function entry to the last use, while it's usually cheaper to
recalculate.

Added:
    llvm/trunk/test/Transforms/SafeStack/phi.ll
    llvm/trunk/test/Transforms/SafeStack/sink-to-use.ll
Modified:
    llvm/trunk/lib/CodeGen/SafeStack.cpp
    llvm/trunk/test/Transforms/SafeStack/array-aligned.ll
    llvm/trunk/test/Transforms/SafeStack/array.ll
    llvm/trunk/test/Transforms/SafeStack/struct.ll

Modified: llvm/trunk/lib/CodeGen/SafeStack.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SafeStack.cpp?rev=272969&r1=272968&r2=272969&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SafeStack.cpp (original)
+++ llvm/trunk/lib/CodeGen/SafeStack.cpp Thu Jun 16 17:34:04 2016
@@ -606,16 +606,39 @@ Value *SafeStack::moveStaticAllocasToUns
     StaticOffset += Size;
     StaticOffset = alignTo(StaticOffset, Align);
 
-    Value *Off = IRB.CreateGEP(BasePointer, // BasePointer is i8*
-                               ConstantInt::get(Int32Ty, -StaticOffset));
-    Value *NewAI = IRB.CreateBitCast(Off, AI->getType(), AI->getName());
-    if (AI->hasName() && isa<Instruction>(NewAI))
-      cast<Instruction>(NewAI)->takeName(AI);
-
-    // Replace alloc with the new location.
     replaceDbgDeclareForAlloca(AI, BasePointer, DIB, /*Deref=*/true, -StaticOffset);
     replaceDbgValueForAlloca(AI, BasePointer, DIB, -StaticOffset);
-    AI->replaceAllUsesWith(NewAI);
+
+    // Replace uses of the alloca with the new location.
+    // Insert address calculation close to each use to work around PR27844.
+    std::string Name = std::string(AI->getName()) + ".unsafe";
+    while (!AI->use_empty()) {
+      Use &U = *AI->use_begin();
+      Instruction *User = cast<Instruction>(U.getUser());
+
+      Instruction *InsertBefore;
+      if (auto *PHI = dyn_cast<PHINode>(User))
+        InsertBefore = PHI->getIncomingBlock(U)->getTerminator();
+      else
+        InsertBefore = User;
+
+      IRBuilder<> IRBUser(InsertBefore);
+      Value *Off = IRBUser.CreateGEP(BasePointer, // BasePointer is i8*
+                                     ConstantInt::get(Int32Ty, -StaticOffset));
+      Value *Replacement = IRBUser.CreateBitCast(Off, AI->getType(), Name);
+
+      if (auto *PHI = dyn_cast<PHINode>(User)) {
+        // PHI nodes may have multiple incoming edges from the same BB (why??),
+        // all must be updated at once with the same incoming value.
+        auto *BB = PHI->getIncomingBlock(U);
+        for (unsigned I = 0; I < PHI->getNumIncomingValues(); ++I)
+          if (PHI->getIncomingBlock(I) == BB)
+            PHI->setIncomingValue(I, Replacement);
+      } else {
+        U.set(Replacement);
+      }
+    }
+
     AI->eraseFromParent();
   }
 

Modified: llvm/trunk/test/Transforms/SafeStack/array-aligned.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SafeStack/array-aligned.ll?rev=272969&r1=272968&r2=272969&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SafeStack/array-aligned.ll (original)
+++ llvm/trunk/test/Transforms/SafeStack/array-aligned.ll Thu Jun 16 17:34:04 2016
@@ -13,16 +13,15 @@ entry:
 
   ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
 
-  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   %a.addr = alloca i8*, align 8
-
-  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
-  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [16 x i8]*
   %buf = alloca [16 x i8], align 16
 
+  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
   store i8* %a, i8** %a.addr, align 8
 
+  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [16 x i8]*
   ; CHECK: %[[GEP:.*]] = getelementptr inbounds [16 x i8], [16 x i8]* %[[BUFPTR2]], i32 0, i32 0
   %gep = getelementptr inbounds [16 x i8], [16 x i8]* %buf, i32 0, i32 0
 

Modified: llvm/trunk/test/Transforms/SafeStack/array.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SafeStack/array.ll?rev=272969&r1=272968&r2=272969&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SafeStack/array.ll (original)
+++ llvm/trunk/test/Transforms/SafeStack/array.ll Thu Jun 16 17:34:04 2016
@@ -17,16 +17,15 @@ entry:
 
   ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
 
-  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   %a.addr = alloca i8*, align 8
-
-  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -4
-  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [4 x i8]*
   %buf = alloca [4 x i8], align 1
 
+  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
   store i8* %a, i8** %a.addr, align 8
 
+  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -4
+  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to [4 x i8]*
   ; CHECK: %[[GEP:.*]] = getelementptr inbounds [4 x i8], [4 x i8]* %[[BUFPTR2]], i32 0, i32 0
   %gep = getelementptr inbounds [4 x i8], [4 x i8]* %buf, i32 0, i32 0
 

Added: llvm/trunk/test/Transforms/SafeStack/phi.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SafeStack/phi.ll?rev=272969&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SafeStack/phi.ll (added)
+++ llvm/trunk/test/Transforms/SafeStack/phi.ll Thu Jun 16 17:34:04 2016
@@ -0,0 +1,35 @@
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+
+define void @f(i1 %d1, i1 %d2) safestack {
+entry:
+; CHECK-LABEL: define void @f(
+; CHECK:         %[[USP:.*]] = load i8*, i8** @__safestack_unsafe_stack_ptr
+; CHECK-NEXT:    getelementptr i8, i8* %[[USP]], i32 -16
+; CHECK:         br i1 %d1, label %[[BB0:.*]], label %[[BB1:.*]]
+  %a = alloca i32, align 8
+  %b = alloca i32, align 8
+  br i1 %d1, label %bb0, label %bb1
+
+bb0:
+; CHECK: [[BB0]]:
+; CHECK: %[[Ai8:.*]] = getelementptr i8, i8* %unsafe_stack_ptr, i32
+; CHECK: %[[AUNSAFE:.*]] = bitcast i8* %[[Ai8]] to i32*
+; CHECK: br i1
+  br i1 %d2, label %bb2, label %bb2
+
+bb1:
+; CHECK: [[BB1]]:
+; CHECK: %[[Bi8:.*]] = getelementptr i8, i8* %unsafe_stack_ptr, i32
+; CHECK: %[[BUNSAFE:.*]] = bitcast i8* %[[Bi8]] to i32*
+; CHECK: br label
+  br label %bb2
+
+bb2:
+; CHECK: phi i32* [ %[[AUNSAFE]], %[[BB0]] ], [ %[[AUNSAFE]], %[[BB0]] ], [ %[[BUNSAFE]], %[[BB1]] ]
+  %c = phi i32* [ %a, %bb0 ], [ %a, %bb0 ], [ %b, %bb1 ]
+  call void @capture(i32* %c)
+  ret void
+}
+
+declare void @capture(i32*)

Added: llvm/trunk/test/Transforms/SafeStack/sink-to-use.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SafeStack/sink-to-use.ll?rev=272969&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SafeStack/sink-to-use.ll (added)
+++ llvm/trunk/test/Transforms/SafeStack/sink-to-use.ll Thu Jun 16 17:34:04 2016
@@ -0,0 +1,22 @@
+; Test that unsafe alloca address calculation is done immediately before each use.
+; RUN: opt -safe-stack -S -mtriple=x86_64-pc-linux-gnu < %s -o - | FileCheck %s
+; RUN: opt -safe-stack -S -mtriple=i386-pc-linux-gnu < %s -o - | FileCheck %s
+
+define void @f() safestack {
+entry:
+  %x0 = alloca i32, align 4
+  %x1 = alloca i32, align 4
+
+; CHECK: %[[A:.*]] = getelementptr i8, i8* %{{.*}}, i32 -4
+; CHECK: %[[X0:.*]] = bitcast i8* %[[A]] to i32*
+; CHECK: call void @use(i32* %[[X0]])
+  call void @use(i32* %x0)
+
+; CHECK: %[[B:.*]] = getelementptr i8, i8* %{{.*}}, i32 -8
+; CHECK: %[[X1:.*]] = bitcast i8* %[[B]] to i32*
+; CHECK: call void @use(i32* %[[X1]])
+  call void @use(i32* %x1)
+  ret void
+}
+
+declare void @use(i32*)

Modified: llvm/trunk/test/Transforms/SafeStack/struct.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SafeStack/struct.ll?rev=272969&r1=272968&r2=272969&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/SafeStack/struct.ll (original)
+++ llvm/trunk/test/Transforms/SafeStack/struct.ll Thu Jun 16 17:34:04 2016
@@ -15,16 +15,15 @@ entry:
 
   ; CHECK: store i8* %[[USST]], i8** @__safestack_unsafe_stack_ptr
 
-  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   %a.addr = alloca i8*, align 8
-
-  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
-  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to %struct.foo*
   %buf = alloca %struct.foo, align 1
 
+  ; CHECK: %[[AADDR:.*]] = alloca i8*, align 8
   ; CHECK: store i8* {{.*}}, i8** %[[AADDR]], align 8
   store i8* %a, i8** %a.addr, align 8
 
+  ; CHECK: %[[BUFPTR:.*]] = getelementptr i8, i8* %[[USP]], i32 -16
+  ; CHECK: %[[BUFPTR2:.*]] = bitcast i8* %[[BUFPTR]] to %struct.foo*
   ; CHECK: %[[GEP:.*]] = getelementptr inbounds %struct.foo, %struct.foo* %[[BUFPTR2]], i32 0, i32 0, i32 0
   %gep = getelementptr inbounds %struct.foo, %struct.foo* %buf, i32 0, i32 0, i32 0
 




More information about the llvm-commits mailing list