diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -130,8 +130,14 @@ let OperandType = "OPERAND_LOCAL" in def local_op : Operand; -let OperandType = "OPERAND_GLOBAL" in -def global_op : Operand; +let OperandType = "OPERAND_GLOBAL" in { + // The operand to global instructions is always a 32-bit index. + def global_op32 : Operand; + // In PIC mode however, we temporarily represent this index as an external + // symbol, which to LLVM is a pointer, so in wasm64 mode it is easiest to + // pretend we use a 64-bit index for it. + def global_op64 : Operand; +} let OperandType = "OPERAND_I32IMM" in def i32imm_op : Operand; @@ -251,7 +257,7 @@ // local.get and local.set are not generated by instruction selection; they // are implied by virtual register uses and defs. -multiclass LOCAL { +multiclass LOCAL { let hasSideEffects = 0 in { // COPY is not an actual instruction in wasm, but since we allow local.get and // local.set to be implicit during most of codegen, we can have a COPY which @@ -312,13 +318,13 @@ } // hasSideEffects = 0 } -defm "" : LOCAL; -defm "" : LOCAL; -defm "" : LOCAL; -defm "" : LOCAL; -defm "" : LOCAL, Requires<[HasSIMD128]>; -defm "" : LOCAL, Requires<[HasReferenceTypes]>; -defm "" : LOCAL, Requires<[HasReferenceTypes]>; +defm "" : LOCAL; +defm "" : LOCAL; // 64-bit only needed for pointers. +defm "" : LOCAL; +defm "" : LOCAL; +defm "" : LOCAL, Requires<[HasSIMD128]>; +defm "" : LOCAL, Requires<[HasReferenceTypes]>; +defm "" : LOCAL, Requires<[HasReferenceTypes]>; let isMoveImm = 1, isAsCheapAsAMove = 1, isReMaterializable = 1 in { defm CONST_I32 : I<(outs I32:$res), (ins i32imm_op:$imm), @@ -346,6 +352,8 @@ def : Pat<(i32 (WebAssemblywrapper tglobaladdr:$addr)), (GLOBAL_GET_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>; +def : Pat<(i64 (WebAssemblywrapper tglobaladdr:$addr)), + (GLOBAL_GET_I64 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr64]>; def : Pat<(i32 (WebAssemblywrapperPIC tglobaladdr:$addr)), (CONST_I32 tglobaladdr:$addr)>, Requires<[IsPIC, HasAddr32]>; @@ -359,6 +367,8 @@ def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)), (GLOBAL_GET_I32 texternalsym:$addr)>, Requires<[IsPIC, HasAddr32]>; +def : Pat<(i64 (WebAssemblywrapper texternalsym:$addr)), + (GLOBAL_GET_I64 texternalsym:$addr)>, Requires<[IsPIC, HasAddr64]>; def : Pat<(i32 (WebAssemblywrapper texternalsym:$addr)), (CONST_I32 texternalsym:$addr)>, Requires<[IsNotPIC, HasAddr32]>; diff --git a/llvm/test/CodeGen/WebAssembly/load-store-pic.ll b/llvm/test/CodeGen/WebAssembly/load-store-pic.ll --- a/llvm/test/CodeGen/WebAssembly/load-store-pic.ll +++ b/llvm/test/CodeGen/WebAssembly/load-store-pic.ll @@ -1,12 +1,11 @@ -; RUN: llc < %s -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -; RUN: llc < %s -asm-verbose=false -relocation-model=pic -fast-isel=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK +; RUN: llc < %s --mtriple=wasm32-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i32 +; RUN: llc < %s --mtriple=wasm32-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i32 +; RUN: llc < %s --mtriple=wasm64-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i64 +; RUN: llc < %s --mtriple=wasm64-unknown-emscripten -asm-verbose=false -relocation-model=pic -fast-isel=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s -check-prefixes=PIC,CHECK -DPTR=i64 ; Test that globals assemble as expected with -fPIC. ; We test here both with and without fast-isel. -target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" -target triple = "wasm32-unknown-emscripten" - @hidden_global = external hidden global i32 @hidden_global_array = external hidden global [10 x i32] @external_global = external global i32 @@ -20,8 +19,8 @@ define i32 @load_hidden_global() { ; CHECK-LABEL: load_hidden_global: ; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; PIC-NEXT: i32.load $push[[L3:[0-9]+]]=, 0($pop[[L2]]){{$}} ; CHECK-NEXT: end_function @@ -32,10 +31,10 @@ define i32 @load_hidden_global_offset() { ; CHECK-LABEL: load_hidden_global_offset: ; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1:[0-9]+]]{{$}} -; PIC-NEXT: i32.const $push[[L3:[0-9]+]]=, 20{{$}} -; PIC-NEXT: i32.add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1:[0-9]+]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L3:[0-9]+]]=, 20{{$}} +; PIC-NEXT: [[PTR]].add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} ; PIC-NEXT: i32.load $push{{[0-9]+}}=, 0($pop[[L4]]){{$}} ; CHECK-NEXT: end_function @@ -49,8 +48,8 @@ define void @store_hidden_global(i32 %n) { ; CHECK-LABEL: store_hidden_global: ; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global@MBREL{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; PIC-NEXT: i32.store 0($pop[[L2]]), $0{{$}} ; CHECK-NEXT: end_function @@ -61,10 +60,10 @@ define void @store_hidden_global_offset(i32 %n) { ; CHECK-LABEL: store_hidden_global_offset: ; PIC: global.get $push[[L0:[0-9]+]]=, __memory_base{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} -; PIC-NEXT: i32.const $push[[L3:[0-9]+]]=, 20{{$}} -; PIC-NEXT: i32.add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, hidden_global_array@MBREL{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L3:[0-9]+]]=, 20{{$}} +; PIC-NEXT: [[PTR]].add $push[[L4:[0-9]+]]=, $pop[[L2]], $pop[[L3]]{{$}} ; PIC-NEXT: i32.store 0($pop[[L4]]), $0{{$}} ; CHECK-NEXT: end_function @@ -92,8 +91,8 @@ define i32 @load_external_global_offset() { ; CHECK-LABEL: load_external_global_offset: ; PIC: global.get $push[[L0:[0-9]+]]=, external_global_array@GOT{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, 20{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, 20{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; PIC-NEXT: i32.load $push{{[0-9]+}}=, 0($pop[[L2]]){{$}} ; CHECK-NEXT: end_function @@ -119,8 +118,8 @@ define void @store_external_global_offset(i32 %n) { ; CHECK-LABEL: store_external_global_offset: ; PIC: global.get $push[[L0:[0-9]+]]=, external_global_array@GOT{{$}} -; PIC-NEXT: i32.const $push[[L1:[0-9]+]]=, 20{{$}} -; PIC-NEXT: i32.add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} +; PIC-NEXT: [[PTR]].const $push[[L1:[0-9]+]]=, 20{{$}} +; PIC-NEXT: [[PTR]].add $push[[L2:[0-9]+]]=, $pop[[L0]], $pop[[L1]]{{$}} ; PIC-NEXT: i32.store 0($pop[[L2]]), $0{{$}} ; CHECK-NEXT: end_function @@ -130,4 +129,4 @@ ret void } -; PIC: .globaltype __memory_base, i32 +; PIC: .globaltype __memory_base, [[PTR]]