From: Dan Gohman Date: Sun, 6 Dec 2015 19:33:32 +0000 (+0000) Subject: [WebAssembly] Enable folding of offsets into global variable addresses. X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=4693393907a37825c48332f7dad147cb2764441a;ds=sidebyside [WebAssembly] Enable folding of offsets into global variable addresses. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254882 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp index 6e1283b4d33..85fb753ed0e 100644 --- a/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -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(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 diff --git a/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp index dd9358035a8..2d2adeb93d2 100644 --- a/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp +++ b/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp @@ -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 index 00000000000..19b110fcfa8 --- /dev/null +++ b/test/CodeGen/WebAssembly/offset-folding.ll @@ -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) +}