diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp @@ -101,10 +101,12 @@ WebAssemblyFrameLowering::getOpcConst(MF) && MRI.hasOneNonDBGUse(Def->getOperand(0).getReg())) { MachineOperand &ImmMO = Def->getOperand(1); - ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset)); - MI.getOperand(FIOperandNum) - .ChangeToRegister(FrameRegister, /*isDef=*/false); - return; + if (ImmMO.isImm()) { + ImmMO.setImm(ImmMO.getImm() + uint32_t(FrameOffset)); + MI.getOperand(FIOperandNum) + .ChangeToRegister(FrameRegister, /*isDef=*/false); + return; + } } } } diff --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll --- a/llvm/test/CodeGen/WebAssembly/userstack.ll +++ b/llvm/test/CodeGen/WebAssembly/userstack.ll @@ -328,6 +328,22 @@ ret void } +; We optimize the format of "frame offset + operand" by folding it, but this is +; only possible when that operand is an immediate. In this example it is a +; global address, so we should not fold it. +; CHECK-LABEL: frame_offset_with_global_address +; CHECK: i[[PTR]].const ${{.*}}=, str +@str = local_unnamed_addr global [3 x i8] c"abc", align 16 +define i8 @frame_offset_with_global_address() { + %1 = alloca i8, align 4 + %2 = ptrtoint i8* %1 to i32 + ;; Here @str is a global address and not an immediate, so cannot be folded + %3 = getelementptr [3 x i8], [3 x i8]* @str, i32 0, i32 %2 + %4 = load i8, i8* %3, align 8 + %5 = and i8 %4, 67 + ret i8 %5 +} + ; CHECK: .globaltype __stack_pointer, i[[PTR]]{{$}} ; TODO: test over-aligned alloca