[llvm] 3e16e21 - GlobalISel: Handle llvm.localescape

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 12:19:09 PDT 2020


Author: Matt Arsenault
Date: 2020-08-04T15:19:02-04:00
New Revision: 3e16e2152cd1fb3914d4da47d83d5e023dd3f2cb

URL: https://github.com/llvm/llvm-project/commit/3e16e2152cd1fb3914d4da47d83d5e023dd3f2cb
DIFF: https://github.com/llvm/llvm-project/commit/3e16e2152cd1fb3914d4da47d83d5e023dd3f2cb.diff

LOG: GlobalISel: Handle llvm.localescape

This one is pretty easy and shrinks the list of unhandled
intrinsics. I'm not sure how relevant the insert point is. Using the
insert position of EntryBuilder will place this after
constants. SelectionDAG seems to end up emitting these after argument
copies and before anything else, but I don't think it really
matters. This also ends up emitting these in the opposite order from
SelectionDAG, but I don't think that matters either.

This also needs a fix to stop the later passes dropping this as a dead
instruction. DeadMachineInstructionElim's version of isDead special
cases LOCAL_ESCAPE for some reason, and I'm not sure why it's excluded
from MachineInstr::isLabel (or why isDead doesn't check it).

I also noticed DeadMachineInstructionElim never considers inline asm
as dead, but GlobalISel will drop asm with no constraints.

Added: 
    llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-localescape.ll
    llvm/test/CodeGen/AArch64/GlobalISel/labels-are-not-dead.mir

Modified: 
    llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
    llvm/lib/CodeGen/GlobalISel/Utils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index be669eca0f6f..ac867b44b574 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -29,6 +29,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineMemOperand.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/StackProtector.h"
@@ -1658,6 +1659,33 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
       .addUse(getOrCreateVReg(*CI.getArgOperand(1)));
     return true;
   }
+  case Intrinsic::localescape: {
+    MachineBasicBlock &EntryMBB = MF->front();
+    StringRef EscapedName = GlobalValue::dropLLVMManglingEscape(MF->getName());
+
+    // Directly emit some LOCAL_ESCAPE machine instrs. Label assignment emission
+    // is the same on all targets.
+    for (unsigned Idx = 0, E = CI.getNumArgOperands(); Idx < E; ++Idx) {
+      Value *Arg = CI.getArgOperand(Idx)->stripPointerCasts();
+      if (isa<ConstantPointerNull>(Arg))
+        continue; // Skip null pointers. They represent a hole in index space.
+
+      int FI = getOrCreateFrameIndex(*cast<AllocaInst>(Arg));
+      MCSymbol *FrameAllocSym =
+          MF->getMMI().getContext().getOrCreateFrameAllocSymbol(EscapedName,
+                                                                Idx);
+
+      // This should be inserted at the start of the entry block.
+      auto LocalEscape =
+          MIRBuilder.buildInstrNoInsert(TargetOpcode::LOCAL_ESCAPE)
+              .addSym(FrameAllocSym)
+              .addFrameIndex(FI);
+
+      EntryMBB.insert(EntryMBB.begin(), LocalEscape);
+    }
+
+    return true;
+  }
 #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC)  \
   case Intrinsic::INTRINSIC:
 #include "llvm/IR/ConstrainedOps.def"

diff  --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 4a7513f23c6b..7fc738adb339 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -180,6 +180,14 @@ bool llvm::canReplaceReg(Register DstReg, Register SrcReg,
 
 bool llvm::isTriviallyDead(const MachineInstr &MI,
                            const MachineRegisterInfo &MRI) {
+  // FIXME: This logical is mostly duplicated with
+  // DeadMachineInstructionElim::isDead. Why is LOCAL_ESCAPE not considered in
+  // MachineInstr::isLabel?
+
+  // Don't delete frame allocation labels.
+  if (MI.getOpcode() == TargetOpcode::LOCAL_ESCAPE)
+    return false;
+
   // If we can move an instruction, we can remove it.  Otherwise, it has
   // a side-effect of some sort.
   bool SawStore = false;

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-localescape.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-localescape.ll
new file mode 100644
index 000000000000..60eaea4e287b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-localescape.ll
@@ -0,0 +1,70 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -global-isel -mtriple=arm64-windows -stop-after=irtranslator -o - %s | FileCheck %s
+
+define void @local_escape() {
+  ; CHECK-LABEL: name: local_escape
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_1>, %stack.1.b
+  ; CHECK:   LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_0>, %stack.0.a
+  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
+  ; CHECK:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+  ; CHECK:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.a
+  ; CHECK:   [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.b
+  ; CHECK:   G_STORE [[C]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %ir.a)
+  ; CHECK:   G_STORE [[C1]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %ir.b)
+  ; CHECK:   RET_ReallyLR
+  %a = alloca i32
+  %b = alloca i32, i32 2
+  call void (...) @llvm.localescape(i32* %a, i32* %b)
+  store i32 42, i32* %a
+  store i32 13, i32* %b
+  ret void
+}
+
+; Try some instructions before the localescape, and use a null
+define void @local_escape_insert_point() {
+  ; CHECK-LABEL: name: local_escape_insert_point
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   LOCAL_ESCAPE <mcsymbol .Llocal_escape_insert_point$frame_escape_2>, %stack.1.b
+  ; CHECK:   LOCAL_ESCAPE <mcsymbol .Llocal_escape_insert_point$frame_escape_0>, %stack.0.a
+  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
+  ; CHECK:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+  ; CHECK:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.a
+  ; CHECK:   [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1.b
+  ; CHECK:   G_STORE [[C]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %ir.a)
+  ; CHECK:   G_STORE [[C1]](s32), [[FRAME_INDEX1]](p0) :: (store 4 into %ir.b)
+  ; CHECK:   RET_ReallyLR
+  %a = alloca i32
+  %b = alloca i32, i32 2
+  store i32 42, i32* %a
+  store i32 13, i32* %b
+  call void (...) @llvm.localescape(i32* %a, i32* null, i32* %b)
+  ret void
+}
+
+declare void @foo([128 x i32]*)
+
+; Check a cast of an alloca
+define void @local_escape_strip_ptr_cast() {
+  ; CHECK-LABEL: name: local_escape_strip_ptr_cast
+  ; CHECK: bb.1 (%ir-block.0):
+  ; CHECK:   LOCAL_ESCAPE <mcsymbol .Llocal_escape_strip_ptr_cast$frame_escape_0>, %stack.0.a
+  ; CHECK:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
+  ; CHECK:   [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0.a
+  ; CHECK:   G_STORE [[C]](s32), [[FRAME_INDEX]](p0) :: (store 4 into %ir.cast)
+  ; CHECK:   ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp
+  ; CHECK:   $x0 = COPY [[FRAME_INDEX]](p0)
+  ; CHECK:   BL @foo, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit $x0
+  ; CHECK:   ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp
+  ; CHECK:   RET_ReallyLR
+  %a = alloca [128 x i32]
+  %cast = bitcast [128 x i32]* %a to i32*
+  store i32 42, i32* %cast
+  call void (...) @llvm.localescape(i32* %cast, i32* null)
+  call void @foo([128 x i32]* %a)
+  ret void
+}
+
+declare void @llvm.localescape(...) #0
+
+attributes #0 = { nounwind }

diff  --git a/llvm/test/CodeGen/AArch64/GlobalISel/labels-are-not-dead.mir b/llvm/test/CodeGen/AArch64/GlobalISel/labels-are-not-dead.mir
new file mode 100644
index 000000000000..ae7c7d3d6c6d
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/labels-are-not-dead.mir
@@ -0,0 +1,34 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=aarch64 -run-pass=legalizer %s -o - | FileCheck %s
+
+# The LOCAL_ESCAPE instructions should not be deleted as dead.
+
+---
+name: no_erase_local_escape
+tracksRegLiveness: true
+stack:
+  - { id: 0, size: 4, alignment: 4 }
+  - { id: 1, size: 8, alignment: 4 }
+body:             |
+  bb.0:
+    ; CHECK-LABEL: name: no_erase_local_escape
+    ; CHECK: LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_0>, %stack.0
+    ; CHECK: LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_1>, %stack.1
+    ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 42
+    ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK: [[FRAME_INDEX:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.0
+    ; CHECK: [[FRAME_INDEX1:%[0-9]+]]:_(p0) = G_FRAME_INDEX %stack.1
+    ; CHECK: G_STORE [[C]](s32), [[FRAME_INDEX]](p0) :: (store 4)
+    ; CHECK: G_STORE [[C1]](s32), [[FRAME_INDEX1]](p0) :: (store 4)
+    ; CHECK: RET_ReallyLR
+    LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_0>, %stack.0
+    LOCAL_ESCAPE <mcsymbol .Llocal_escape$frame_escape_1>, %stack.1
+    %2:_(s32) = G_CONSTANT i32 42
+    %3:_(s32) = G_CONSTANT i32 13
+    %0:_(p0) = G_FRAME_INDEX %stack.0
+    %1:_(p0) = G_FRAME_INDEX %stack.1
+    G_STORE %2(s32), %0(p0) :: (store 4)
+    G_STORE %3(s32), %1(p0) :: (store 4)
+    RET_ReallyLR
+
+...


        


More information about the llvm-commits mailing list