Skip to content

Commit

Permalink
[ARM] Correctly handle execute-only in EmitStructByval
Browse files Browse the repository at this point in the history
Currently when compiling for an execute-only target without movt then
EmitStructByval will generate a constant pool load which isn't
compatible with execute-only. Handle this by emitting tMOVi32imm,
and also simplify the existing movt handling by emitting t2MOVi32imm
or MOVi32imm.

Differential Revision: https://reviews.llvm.org/D154944
  • Loading branch information
john-brawn-arm committed Jul 19, 2023
1 parent 1b12b1a commit cee7e7b
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 12 deletions.
18 changes: 6 additions & 12 deletions llvm/lib/Target/ARM/ARMISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11493,18 +11493,12 @@ ARMTargetLowering::EmitStructByval(MachineInstr &MI,
// Load an immediate to varEnd.
Register varEnd = MRI.createVirtualRegister(TRC);
if (Subtarget->useMovt()) {
unsigned Vtmp = varEnd;
if ((LoopSize & 0xFFFF0000) != 0)
Vtmp = MRI.createVirtualRegister(TRC);
BuildMI(BB, dl, TII->get(IsThumb ? ARM::t2MOVi16 : ARM::MOVi16), Vtmp)
.addImm(LoopSize & 0xFFFF)
.add(predOps(ARMCC::AL));

if ((LoopSize & 0xFFFF0000) != 0)
BuildMI(BB, dl, TII->get(IsThumb ? ARM::t2MOVTi16 : ARM::MOVTi16), varEnd)
.addReg(Vtmp)
.addImm(LoopSize >> 16)
.add(predOps(ARMCC::AL));
BuildMI(BB, dl, TII->get(IsThumb ? ARM::t2MOVi32imm : ARM::MOVi32imm),
varEnd)
.addImm(LoopSize);
} else if (Subtarget->genExecuteOnly()) {
assert(IsThumb && "Non-thumb expected to have used movt");
BuildMI(BB, dl, TII->get(ARM::tMOVi32imm), varEnd).addImm(LoopSize);
} else {
MachineConstantPool *ConstantPool = MF->getConstantPool();
Type *Int32Ty = Type::getInt32Ty(MF->getFunction().getContext());
Expand Down
21 changes: 21 additions & 0 deletions llvm/test/CodeGen/ARM/execute-only.ll
Original file line number Diff line number Diff line change
Expand Up @@ -207,3 +207,24 @@ define i32 @test_imm_middle_bytes() {

ret i32 u0x223300
}

; This struct is sized so that the byval call does an inline memcpy of
; 0x10001 bytes.
%struct.struct_t = type { [65553 x i8] }
@byval_arg = global %struct.struct_t zeroinitializer
declare void @byval_fn(ptr byval(%struct.struct_t))

define void @test_byval_call() {
entry:
; CHECK-LABEL: test_byval_call:
; CHECK-T2BASE: movw [[BYVAL_CPYSIZE:r[0-9]+]], #1
; CHECK-T2: movs [[BYVAL_CPYSIZE:r[0-9]+]], #1
; CHECK: movt [[BYVAL_CPYSIZE]], #1
; CHECK-T1-LABEL: test_byval_call:
; CHECK-T1: movs [[BYVAL_CPYSIZE:r[0-9]+]], #1
; CHECK-T1: lsls [[BYVAL_CPYSIZE]], [[BYVAL_CPYSIZE]], #16
; CHECK-T1: adds [[BYVAL_CPYSIZE]], #1

call void @byval_fn(ptr byval(%struct.struct_t) @byval_arg)
ret void
}

0 comments on commit cee7e7b

Please sign in to comment.