[PATCH] D69534: [X86] Lower frame references with large offsets

David Greene via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 29 14:33:48 PDT 2019


greened updated this revision to Diff 226971.
greened added a comment.

This revision avoids the more general use of register scavenging, opting instead for a local register scavenger which can operate in backward mode, which doesn't need up-to-date liveness information.  This seems safer to me, avoiding lots of potentially unknown pitfalls in the X86 backend.

I am not sure whether the `FIXME` actually applies.  If the scavenger is guaranteed to return a stack slot with a small offset, then we can lift the spilling restriction.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D69534/new/

https://reviews.llvm.org/D69534

Files:
  llvm/lib/Target/X86/X86RegisterInfo.cpp
  llvm/test/CodeGen/X86/large-stack-offset.ll


Index: llvm/test/CodeGen/X86/large-stack-offset.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/large-stack-offset.ll
@@ -0,0 +1,34 @@
+; Test that we can support a large immediate offset on the stack.
+;
+; RUN: llc %s -o - | FileCheck %s
+;
+; ModuleID = 'bugpoint-reduced-simplified.bc'
+source_filename = "test.c"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+ at .str.7 = external dso_local unnamed_addr constant [73 x i8], align 1
+
+; Function Attrs: noinline optnone
+define dso_local void @main() local_unnamed_addr #0 {
+entry:
+  %result = alloca [1048576000 x double], align 16
+  br i1 undef, label %if.then, label %if.end
+
+if.then:                                          ; preds = %entry
+  unreachable
+
+if.end:                                           ; preds = %entry
+  %arrayidx34 = getelementptr inbounds [1048576000 x double], [1048576000 x double]* %result, i64 0, i64 262143999
+; CHECK: movabsq{{[[:space:]]+}}$2298478584,{{[[:space:]]+}}[[INDEX:%[a-z]+]]{{[[:space:]]+}}# imm = 0x88FFFFF8
+; CHECK-NEXT: movsd{{[[:space:]]+}}(%rbp,[[INDEX]]),{{[[:space:]]+}}{{%[a-z0-9]+}}
+
+  %0 = load double, double* %arrayidx34, align 8
+  call void (i8*, ...) @printf(i8* getelementptr inbounds ([73 x i8], [73 x i8]* @.str.7, i64 0, i64 0), i32 undef, i32 262143999, double %0, i32 524287999, double undef, i32 786431999, double undef, i32 1048575999, double undef)
+  ret void
+}
+
+declare dso_local void @printf(i8*, ...) local_unnamed_addr #1
+
+attributes #0 = { noinline optnone "frame-pointer"="all" "no-infs-fp-math"="false" }
+attributes #1 = { "use-soft-float"="false" }
Index: llvm/lib/Target/X86/X86RegisterInfo.cpp
===================================================================
--- llvm/lib/Target/X86/X86RegisterInfo.cpp
+++ llvm/lib/Target/X86/X86RegisterInfo.cpp
@@ -22,6 +22,7 @@
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
 #include "llvm/CodeGen/TargetFrameLowering.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/IR/Constants.h"
@@ -778,8 +779,41 @@
     // Offset is a 32-bit integer.
     int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
     int Offset = FIOffset + Imm;
-    assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
-           "Requesting 64-bit offset in 32-bit immediate!");
+
+    if (!isInt<32>((long long)FIOffset + Imm)) {
+      // Load the immediate into a register and use SIB addressing.
+      if (!Is64Bit)
+        report_fatal_error("Cannot lower large stack offset in 32-bit mode");
+
+      RegScavenger RS;
+
+      RS.enterBasicBlockEnd(MBB);
+      RS.backward(II);
+
+      // FIXME: Don't allow spilling because we may not be guaranteed to get a
+      // stack slot with a small offset, leading to infinite recursion trying to
+      // materialize the large offset in a register.  This restriction can be
+      // lifted if register scavenger spills are always close to the frame or
+      // stack pointer.
+      Register OffsetReg = RS.scavengeRegisterBackwards(X86::GR64RegClass,
+                                                        II,
+                                                        /*RestoreAfter=*/false,
+                                                        SPAdj,
+                                                        /*AllowSpill=*/false);
+
+      if (!OffsetReg)
+        report_fatal_error("Could not find register for large stack offset");
+
+      const X86InstrInfo *TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
+
+      BuildMI(MBB, II, MI.getDebugLoc(), TII->get(X86::MOV64ri), OffsetReg).
+          addImm((long long)FIOffset + Imm);
+      MI.getOperand(FIOperandNum + X86::AddrIndexReg).setReg(OffsetReg);
+      MI.getOperand(FIOperandNum + X86::AddrIndexReg).setIsKill();
+      MI.getOperand(FIOperandNum + X86::AddrDisp).setImm(0);
+      return;
+    }
+
     if (Offset != 0 || !tryOptimizeLEAtoMOV(II))
       MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
   } else {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D69534.226971.patch
Type: text/x-patch
Size: 4252 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20191029/546b8d38/attachment.bin>


More information about the llvm-commits mailing list