Index: include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h =================================================================== --- include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h +++ include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h @@ -543,6 +543,10 @@ /// /// \return a MachineInstrBuilder for the newly created instruction. MachineInstrBuilder buildCopy(unsigned Res, unsigned Op); + template + MachineInstrBuilder buildCopy(DstType &&Res, SrcType &&Src) { + return buildCopy(getDestFromArg(Res), getRegFromArg(Src)); + } /// Build and insert `Res = G_LOAD Addr, MMO`. /// @@ -660,6 +664,10 @@ /// /// \return The newly created instruction. MachineInstrBuilder buildTrunc(unsigned Res, unsigned Op); + template + MachineInstrBuilder buildTrunc(DstType &&Res, SrcType &&Src) { + return buildTrunc(getDestFromArg(Res), getRegFromArg(Src)); + } /// Build and insert a \p Res = G_ICMP \p Pred, \p Op0, \p Op1 /// Index: lib/CodeGen/GlobalISel/CallLowering.cpp =================================================================== --- lib/CodeGen/GlobalISel/CallLowering.cpp +++ lib/CodeGen/GlobalISel/CallLowering.cpp @@ -160,10 +160,11 @@ // FIXME: bitconverting between vector types may or may not be a // nop in big-endian situations. return ValReg; - case CCValAssign::AExt: + case CCValAssign::AExt: { assert(!VA.getLocVT().isVector() && "unexpected vector extend"); - // Otherwise, it's a nop. - return ValReg; + auto MIB = MIRBuilder.buildAnyExt(LocTy, ValReg); + return MIB->getOperand(0).getReg(); + } case CCValAssign::SExt: { unsigned NewReg = MRI.createGenericVirtualRegister(LocTy); MIRBuilder.buildSExt(NewReg, ValReg); Index: lib/CodeGen/MachineVerifier.cpp =================================================================== --- lib/CodeGen/MachineVerifier.cpp +++ lib/CodeGen/MachineVerifier.cpp @@ -49,6 +49,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" using namespace llvm; namespace { @@ -943,6 +944,19 @@ MI); break; } + case TargetOpcode::COPY: { + const MachineOperand &DstOp = MI->getOperand(0); + const MachineOperand &SrcOp = MI->getOperand(1); + unsigned DstSize = + RegisterBankInfo::getSizeInBits(DstOp.getReg(), *MRI, *TRI); + unsigned SrcSize = + RegisterBankInfo::getSizeInBits(SrcOp.getReg(), *MRI, *TRI); + if (DstSize != SrcSize) + // Catch only obvious cases not involving subregs for now. + if (!DstOp.getSubReg() && !SrcOp.getSubReg()) + report("Copy Instruction is illegal with mismatching sizes", MI); + break; + } case TargetOpcode::STATEPOINT: if (!MI->getOperand(StatepointOpers::IDPos).isImm() || !MI->getOperand(StatepointOpers::NBytesPos).isImm() || Index: lib/Target/AArch64/AArch64CallLowering.cpp =================================================================== --- lib/Target/AArch64/AArch64CallLowering.cpp +++ lib/Target/AArch64/AArch64CallLowering.cpp @@ -70,8 +70,18 @@ void assignValueToReg(unsigned ValVReg, unsigned PhysReg, CCValAssign &VA) override { markPhysRegUsed(PhysReg); - MIRBuilder.buildCopy(ValVReg, PhysReg); - // FIXME: assert extension + switch (VA.getLocInfo()) { + default: + MIRBuilder.buildCopy(ValVReg, PhysReg); + break; + case CCValAssign::LocInfo::SExt: + case CCValAssign::LocInfo::ZExt: + case CCValAssign::LocInfo::AExt: { + auto Copy = MIRBuilder.buildCopy(LLT{VA.getLocVT()}, PhysReg); + MIRBuilder.buildTrunc(ValVReg, Copy); + break; + } + } } void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, Index: test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll +++ test/CodeGen/AArch64/GlobalISel/arm64-callingconv.ll @@ -70,8 +70,10 @@ ; CHECK: %w0 = COPY [[ANSWER]] ; CHECK: %d0 = COPY [[D_ONE]] ; CHECK: %x1 = COPY [[TWELVE]] -; CHECK: %w2 = COPY [[THREE]](s8) -; CHECK: %w3 = COPY [[ONE]](s16) +; CHECK: [[THREE_TMP:%[0-9]+]](s32) = G_ANYEXT [[THREE]] +; CHECK: %w2 = COPY [[THREE_TMP]](s32) +; CHECK: [[ONE_TMP:%[0-9]+]](s32) = G_ANYEXT [[ONE]] +; CHECK: %w3 = COPY [[ONE_TMP]](s32) ; CHECK: %w4 = COPY [[FOUR]](s32) ; CHECK: %s1 = COPY [[F_ONE]](s32) ; CHECK: %d2 = COPY [[TWO]](s64) Index: test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll +++ test/CodeGen/AArch64/GlobalISel/arm64-fallback.ll @@ -43,7 +43,7 @@ ; The key problem here is that we may fail to create an MBB referenced by a ; PHI. If so, we cannot complete the G_PHI and mustn't try or bad things ; happen. -; FALLBACK-WITH-REPORT-ERR: remark: :0:0: cannot select: G_STORE %vreg5, %vreg2; mem:ST4[%addr] GPR:%vreg5,%vreg2 (in function: pending_phis) +; FALLBACK-WITH-REPORT-ERR: remark: :0:0: cannot select: G_STORE %vreg6, %vreg2; mem:ST4[%addr] GPR:%vreg6,%vreg2 (in function: pending_phis) ; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for pending_phis ; FALLBACK-WITH-REPORT-OUT-LABEL: pending_phis: define i32 @pending_phis(i1 %tst, i32 %val, i32* %addr) { Index: test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll +++ test/CodeGen/AArch64/GlobalISel/arm64-irtranslator.ll @@ -971,7 +971,8 @@ } ; CHECK-LABEL: name: test_select -; CHECK: [[TST:%[0-9]+]](s1) = COPY %w0 +; CHECK: [[TST_C:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TST:%[0-9]+]](s1) = G_TRUNC [[TST_C]] ; CHECK: [[LHS:%[0-9]+]](s32) = COPY %w1 ; CHECK: [[RHS:%[0-9]+]](s32) = COPY %w2 ; CHECK: [[RES:%[0-9]+]](s32) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]] @@ -982,7 +983,8 @@ } ; CHECK-LABEL: name: test_select_ptr -; CHECK: [[TST:%[0-9]+]](s1) = COPY %w0 +; CHECK: [[TST_C:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TST:%[0-9]+]](s1) = G_TRUNC [[TST_C]] ; CHECK: [[LHS:%[0-9]+]](p0) = COPY %x1 ; CHECK: [[RHS:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[RES:%[0-9]+]](p0) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]] @@ -993,7 +995,8 @@ } ; CHECK-LABEL: name: test_select_vec -; CHECK: [[TST:%[0-9]+]](s1) = COPY %w0 +; CHECK: [[TST_C:%[0-9]+]](s32) = COPY %w0 +; CHECK: [[TST:%[0-9]+]](s1) = G_TRUNC [[TST_C]] ; CHECK: [[LHS:%[0-9]+]](<4 x s32>) = COPY %q0 ; CHECK: [[RHS:%[0-9]+]](<4 x s32>) = COPY %q1 ; CHECK: [[RES:%[0-9]+]](<4 x s32>) = G_SELECT [[TST]](s1), [[LHS]], [[RHS]] @@ -1176,10 +1179,12 @@ define void @test_memset(i8* %dst, i8 %val, i64 %size) { ; CHECK-LABEL: name: test_memset ; CHECK: [[DST:%[0-9]+]](p0) = COPY %x0 -; CHECK: [[SRC:%[0-9]+]](s8) = COPY %w1 +; CHECK: [[SRC_C:%[0-9]+]](s32) = COPY %w1 +; CHECK: [[SRC:%[0-9]+]](s8) = G_TRUNC [[SRC_C]] ; CHECK: [[SIZE:%[0-9]+]](s64) = COPY %x2 ; CHECK: %x0 = COPY [[DST]] -; CHECK: %w1 = COPY [[SRC]] +; CHECK: [[SRC_TMP:%[0-9]+]](s32) = G_ANYEXT [[SRC]] +; CHECK: %w1 = COPY [[SRC_TMP]] ; CHECK: %x2 = COPY [[SIZE]] ; CHECK: BL $memset, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %x0, implicit %w1, implicit %x2 call void @llvm.memset.p0i8.i64(i8* %dst, i8 %val, i64 %size, i32 1, i1 0) Index: test/CodeGen/AArch64/GlobalISel/call-translator.ll =================================================================== --- test/CodeGen/AArch64/GlobalISel/call-translator.ll +++ test/CodeGen/AArch64/GlobalISel/call-translator.ll @@ -61,7 +61,8 @@ ; CHECK-LABEL: name: test_struct_formal ; CHECK: [[DBL:%[0-9]+]](s64) = COPY %d0 ; CHECK: [[I64:%[0-9]+]](s64) = COPY %x0 -; CHECK: [[I8:%[0-9]+]](s8) = COPY %w1 +; CHECK: [[I8_C:%[0-9]+]](s32) = COPY %w1 +; CHECK: [[I8:%[0-9]+]](s8) = G_TRUNC [[I8_C]] ; CHECK: [[ADDR:%[0-9]+]](p0) = COPY %x2 ; CHECK: [[UNDEF:%[0-9]+]](s192) = G_IMPLICIT_DEF @@ -126,7 +127,8 @@ ; CHECK-LABEL: name: test_abi_exts_call ; CHECK: [[VAL:%[0-9]+]](s8) = G_LOAD -; CHECK: %w0 = COPY [[VAL]] +; CHECK: [[VAL_TMP:%[0-9]+]](s32) = G_ANYEXT [[VAL]] +; CHECK: %w0 = COPY [[VAL_TMP]] ; CHECK: BL @take_char, csr_aarch64_aapcs, implicit-def %lr, implicit %sp, implicit %w0 ; CHECK: [[SVAL:%[0-9]+]](s32) = G_SEXT [[VAL]](s8) ; CHECK: %w0 = COPY [[SVAL]](s32) Index: test/Verifier/test_copy.mir =================================================================== --- /dev/null +++ test/Verifier/test_copy.mir @@ -0,0 +1,30 @@ +#RUN: not llc -o - -global-isel -run-pass=none -verify-machineinstrs %s 2>&1 | FileCheck %s +# REQUIRES: global-isel, aarch64-registered-target +--- | + ; ModuleID = 'test.ll' + source_filename = "test.ll" + target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" + target triple = "aarch64-unknown-unknown" + + define i32 @test_copy(i32 %argc) { + ret i32 0 + } + +... +--- +name: test_copy +legalized: true +regBankSelected: false +selected: false +tracksRegLiveness: true +registers: + - { id: 0, class: _, preferred-register: '' } +liveins: +body: | + bb.0: + liveins: %w0 + ; This test is used to catch verifier errors with copys having mismatching sizes + ; CHECK: Bad machine code: Copy Instruction is illegal with mismatching sizes + + %0(s8) = COPY %w0 +...