[llvm] r360604 - [TargetLowering] Handle multi depth GEPs w/ inline asm constraints

Nick Desaulniers via llvm-commits llvm-commits at lists.llvm.org
Mon May 13 10:27:44 PDT 2019


Author: nickdesaulniers
Date: Mon May 13 10:27:44 2019
New Revision: 360604

URL: http://llvm.org/viewvc/llvm-project?rev=360604&view=rev
Log:
[TargetLowering] Handle multi depth GEPs w/ inline asm constraints

Summary:
X86TargetLowering::LowerAsmOperandForConstraint had better support than
TargetLowering::LowerAsmOperandForConstraint for arbitrary depth
getelementpointers for "i", "n", and "s" extended inline assembly
constraints. Hoist its support from the derived class into the base
class.

Link: https://github.com/ClangBuiltLinux/linux/issues/469

Reviewers: echristo, t.p.northover

Reviewed By: t.p.northover

Subscribers: t.p.northover, E5ten, kees, jyknight, nemanjai, javed.absar, eraman, hiraditya, jsji, llvm-commits, void, craig.topper, nathanchance, srhines

Tags: #llvm

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

Added:
    llvm/trunk/test/CodeGen/AArch64/inline-asm-multilevel-gep.ll
    llvm/trunk/test/CodeGen/ARM/inline-asm-multilevel-gep.ll
    llvm/trunk/test/CodeGen/PowerPC/inline-asm-multilevel-gep.ll
    llvm/trunk/test/CodeGen/X86/inline-asm-multilevel-gep.ll
Modified:
    llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
    llvm/trunk/lib/Target/X86/X86ISelLowering.cpp

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp?rev=360604&r1=360603&r2=360604&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp Mon May 13 10:27:44 2019
@@ -3542,46 +3542,41 @@ void TargetLowering::LowerAsmOperandForC
   case 'i':    // Simple Integer or Relocatable Constant
   case 'n':    // Simple Integer
   case 's': {  // Relocatable Constant
-    // These operands are interested in values of the form (GV+C), where C may
-    // be folded in as an offset of GV, or it may be explicitly added.  Also, it
-    // is possible and fine if either GV or C are missing.
-    ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op);
-    GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op);
 
-    // If we have "(add GV, C)", pull out GV/C
-    if (Op.getOpcode() == ISD::ADD) {
-      C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
-      GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(0));
-      if (!C || !GA) {
-        C = dyn_cast<ConstantSDNode>(Op.getOperand(0));
-        GA = dyn_cast<GlobalAddressSDNode>(Op.getOperand(1));
-      }
-      if (!C || !GA) {
-        C = nullptr;
-        GA = nullptr;
-      }
-    }
+    GlobalAddressSDNode *GA;
+    ConstantSDNode *C;
+    uint64_t Offset = 0;
 
-    // If we find a valid operand, map to the TargetXXX version so that the
-    // value itself doesn't get selected.
-    if (GA) {   // Either &GV   or   &GV+C
-      if (ConstraintLetter != 'n') {
-        int64_t Offs = GA->getOffset();
-        if (C) Offs += C->getZExtValue();
-        Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(),
-                                                 C ? SDLoc(C) : SDLoc(),
-                                                 Op.getValueType(), Offs));
-      }
-      return;
-    }
-    if (C) {   // just C, no GV.
-      // Simple constants are not allowed for 's'.
-      if (ConstraintLetter != 's') {
-        // gcc prints these as sign extended.  Sign extend value to 64 bits
-        // now; without this it would get ZExt'd later in
-        // ScheduleDAGSDNodes::EmitNode, which is very generic.
-        Ops.push_back(DAG.getTargetConstant(C->getSExtValue(),
+    // Match (GA) or (C) or (GA+C) or (GA-C) or ((GA+C)+C) or (((GA+C)+C)+C),
+    // etc., since getelementpointer is variadic. We can't use
+    // SelectionDAG::FoldSymbolOffset because it expects the GA to be accessible
+    // while in this case the GA may be furthest from the root node which is
+    // likely an ISD::ADD.
+    while (1) {
+      if ((GA = dyn_cast<GlobalAddressSDNode>(Op)) && ConstraintLetter != 'n') {
+        Ops.push_back(DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(Op),
+                                                 GA->getValueType(0),
+                                                 Offset + GA->getOffset()));
+        return;
+      } else if ((C = dyn_cast<ConstantSDNode>(Op)) &&
+                 ConstraintLetter != 's') {
+        Ops.push_back(DAG.getTargetConstant(Offset + C->getSExtValue(),
                                             SDLoc(C), MVT::i64));
+        return;
+      } else {
+        const unsigned OpCode = Op.getOpcode();
+        if (OpCode == ISD::ADD || OpCode == ISD::SUB) {
+          if ((C = dyn_cast<ConstantSDNode>(Op.getOperand(0))))
+            Op = Op.getOperand(1);
+          // Subtraction is not commutative.
+          else if (OpCode == ISD::ADD &&
+                   (C = dyn_cast<ConstantSDNode>(Op.getOperand(1))))
+            Op = Op.getOperand(0);
+          else
+            return;
+          Offset += (OpCode == ISD::ADD ? 1 : -1) * C->getSExtValue();
+          continue;
+        }
       }
       return;
     }

Modified: llvm/trunk/lib/Target/X86/X86ISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelLowering.cpp?rev=360604&r1=360603&r2=360604&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelLowering.cpp Mon May 13 10:27:44 2019
@@ -44027,40 +44027,12 @@ void X86TargetLowering::LowerAsmOperandF
 
     // If we are in non-pic codegen mode, we allow the address of a global (with
     // an optional displacement) to be used with 'i'.
-    GlobalAddressSDNode *GA = nullptr;
-    int64_t Offset = 0;
-
-    // Match either (GA), (GA+C), (GA+C1+C2), etc.
-    while (1) {
-      if ((GA = dyn_cast<GlobalAddressSDNode>(Op))) {
-        Offset += GA->getOffset();
-        break;
-      } else if (Op.getOpcode() == ISD::ADD) {
-        if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
-          Offset += C->getZExtValue();
-          Op = Op.getOperand(0);
-          continue;
-        }
-      } else if (Op.getOpcode() == ISD::SUB) {
-        if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) {
-          Offset += -C->getZExtValue();
-          Op = Op.getOperand(0);
-          continue;
-        }
-      }
-
-      // Otherwise, this isn't something we can handle, reject it.
-      return;
-    }
-
-    const GlobalValue *GV = GA->getGlobal();
-    // If we require an extra load to get this address, as in PIC mode, we
-    // can't accept it.
-    if (isGlobalStubReference(Subtarget.classifyGlobalReference(GV)))
-      return;
-
-    Result = DAG.getTargetGlobalAddress(GV, SDLoc(Op),
-                                        GA->getValueType(0), Offset);
+    if (auto *GA = dyn_cast<GlobalAddressSDNode>(Op))
+      // If we require an extra load to get this address, as in PIC mode, we
+      // can't accept it.
+      if (isGlobalStubReference(
+              Subtarget.classifyGlobalReference(GA->getGlobal())))
+        return;
     break;
   }
   }

Added: llvm/trunk/test/CodeGen/AArch64/inline-asm-multilevel-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/inline-asm-multilevel-gep.ll?rev=360604&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/inline-asm-multilevel-gep.ll (added)
+++ llvm/trunk/test/CodeGen/AArch64/inline-asm-multilevel-gep.ll Mon May 13 10:27:44 2019
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple aarch64-gnu-linux | FileCheck %s
+
+; @foo is a 2d array of i32s, ex.
+; i32 foo [2][2]
+ at foo = internal global [2 x [2 x i32]] zeroinitializer, align 4
+
+define void @bar() {
+; access foo[1][1]
+; CHECK: // foo+12
+  tail call void asm sideeffect "// ${0:c}", "i"(i32* getelementptr inbounds ([2 x [2 x i32]], [2 x [2 x i32]]* @foo, i64 0, i64 1, i64 1))
+  ret void
+}

Added: llvm/trunk/test/CodeGen/ARM/inline-asm-multilevel-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/inline-asm-multilevel-gep.ll?rev=360604&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/ARM/inline-asm-multilevel-gep.ll (added)
+++ llvm/trunk/test/CodeGen/ARM/inline-asm-multilevel-gep.ll Mon May 13 10:27:44 2019
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple armv7-linux-gnueabi | FileCheck %s
+
+; @foo is a 2d array of i32s, ex.
+; i32 foo [2][2]
+ at foo = internal global [2 x [2 x i32]] zeroinitializer, align 4
+
+define void @bar() {
+; access foo[1][1]
+; CHECK: @ foo+12
+  tail call void asm sideeffect "@ ${0:c}", "i"(i32* getelementptr inbounds ([2 x [2 x i32]], [2 x [2 x i32]]* @foo, i64 0, i64 1, i64 1))
+  ret void
+}

Added: llvm/trunk/test/CodeGen/PowerPC/inline-asm-multilevel-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/PowerPC/inline-asm-multilevel-gep.ll?rev=360604&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/PowerPC/inline-asm-multilevel-gep.ll (added)
+++ llvm/trunk/test/CodeGen/PowerPC/inline-asm-multilevel-gep.ll Mon May 13 10:27:44 2019
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple ppc32-- | FileCheck %s
+
+; @foo is a 2d array of i32s, ex.
+; i32 foo [2][2]
+ at foo = internal global [2 x [2 x i32]] zeroinitializer, align 4
+
+define void @bar() {
+; access foo[1][1]
+; CHECK: # foo+12
+  tail call void asm sideeffect "# ${0:c}", "i"(i32* getelementptr inbounds ([2 x [2 x i32]], [2 x [2 x i32]]* @foo, i64 0, i64 1, i64 1))
+  ret void
+}

Added: llvm/trunk/test/CodeGen/X86/inline-asm-multilevel-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/inline-asm-multilevel-gep.ll?rev=360604&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/X86/inline-asm-multilevel-gep.ll (added)
+++ llvm/trunk/test/CodeGen/X86/inline-asm-multilevel-gep.ll Mon May 13 10:27:44 2019
@@ -0,0 +1,12 @@
+; RUN: llc < %s -mtriple x86_64-gnu-linux | FileCheck %s
+
+; @foo is a 2d array of i32s, ex.
+; i32 foo [2][2]
+ at foo = internal global [2 x [2 x i32]] zeroinitializer, align 4
+
+define void @bar() {
+; access foo[1][1]
+; CHECK: # foo+12
+  tail call void asm sideeffect "# ${0:c}", "i"(i32* getelementptr inbounds ([2 x [2 x i32]], [2 x [2 x i32]]* @foo, i64 0, i64 1, i64 1))
+  ret void
+}




More information about the llvm-commits mailing list