[WebAssembly] Enable folding of offsets into global variable addresses.
authorDan Gohman <dan433584@gmail.com>
Sun, 6 Dec 2015 19:33:32 +0000 (19:33 +0000)
committerDan Gohman <dan433584@gmail.com>
Sun, 6 Dec 2015 19:33:32 +0000 (19:33 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254882 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyISelLowering.cpp
lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
test/CodeGen/WebAssembly/offset-folding.ll [new file with mode: 0644]

index 6e1283b4d3341ae4df0c79f5b509402c2a248430..85fb753ed0e0911780d015e7667a9d378e45aae9 100644 (file)
@@ -196,9 +196,8 @@ FastISel *WebAssemblyTargetLowering::createFastISel(
 
 bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
     const GlobalAddressSDNode * /*GA*/) const {
-  // The WebAssembly target doesn't support folding offsets into global
-  // addresses.
-  return false;
+  // All offsets can be folded.
+  return true;
 }
 
 MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
@@ -528,13 +527,12 @@ SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
   SDLoc DL(Op);
   const auto *GA = cast<GlobalAddressSDNode>(Op);
   EVT VT = Op.getValueType();
-  assert(GA->getOffset() == 0 &&
-         "offsets on global addresses are forbidden by isOffsetFoldingLegal");
   assert(GA->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");
   if (GA->getAddressSpace() != 0)
     fail(DL, DAG, "WebAssembly only expects the 0 address space");
   return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
-                     DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT));
+                     DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
+                                                GA->getOffset()));
 }
 
 SDValue
index dd9358035a883dcde6182bc3cce601258fa839ac..2d2adeb93d2da978e71c52811250598ca5d05f23 100644 (file)
@@ -39,11 +39,16 @@ MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
 
 MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
                                                      MCSymbol *Sym) const {
+  assert(MO.getTargetFlags() == 0 && "WebAssembly does not use target flags");
 
   const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
 
-  if (!MO.isJTI() && MO.getOffset())
-    llvm_unreachable("unknown symbol op");
+  int64_t Offset = MO.getOffset();
+  if (Offset != 0) {
+    assert(!MO.isJTI() && "Unexpected offset with jump table index");
+    Expr =
+        MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
+  }
 
   return MCOperand::createExpr(Expr);
 }
diff --git a/test/CodeGen/WebAssembly/offset-folding.ll b/test/CodeGen/WebAssembly/offset-folding.ll
new file mode 100644 (file)
index 0000000..19b110f
--- /dev/null
@@ -0,0 +1,45 @@
+; RUN: llc < %s -asm-verbose=false | FileCheck %s
+
+; Test that constant offsets can be folded into global addresses.
+
+target datalayout = "e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+@x = external global [0 x i32]
+@y = global [50 x i32] zeroinitializer
+
+; Test basic constant offsets of both defined and external symbols.
+
+; CHECK-LABEL: test0:
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: i32.const $push0=, x+188{{$}}
+; CHECK=NEXT: return $pop0{{$}}
+define i32* @test0() {
+  ret i32* getelementptr ([0 x i32], [0 x i32]* @x, i32 0, i32 47)
+}
+
+; CHECK-LABEL: test1:
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: i32.const $push0=, y+188{{$}}
+; CHECK=NEXT: return $pop0{{$}}
+define i32* @test1() {
+  ret i32* getelementptr ([50 x i32], [50 x i32]* @y, i32 0, i32 47)
+}
+
+; Test zero offsets.
+
+; CHECK-LABEL: test2:
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: i32.const $push0=, x{{$}}
+; CHECK=NEXT: return $pop0{{$}}
+define i32* @test2() {
+  ret i32* getelementptr ([0 x i32], [0 x i32]* @x, i32 0, i32 0)
+}
+
+; CHECK-LABEL: test3:
+; CHECK-NEXT: .result i32{{$}}
+; CHECK-NEXT: i32.const $push0=, y{{$}}
+; CHECK=NEXT: return $pop0{{$}}
+define i32* @test3() {
+  ret i32* getelementptr ([50 x i32], [50 x i32]* @y, i32 0, i32 0)
+}