// 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);
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,
assert(VA.isRegLoc() && "Value shouldn't be assigned to reg");
assert(VA.getLocReg() == PhysReg && "Assigning to the wrong reg?");
- assert(VA.getValVT().getSizeInBits() <= 64 && "Unsupported value size");
- assert(VA.getLocVT().getSizeInBits() <= 64 && "Unsupported location size");
+ auto ValSize = VA.getValVT().getSizeInBits();
+ auto LocSize = VA.getLocVT().getSizeInBits();
+
+ assert(ValSize <= 64 && "Unsupported value size");
+ assert(LocSize <= 64 && "Unsupported location size");
- // The necessary extensions are handled on the other side of the ABI
- // boundary.
markPhysRegUsed(PhysReg);
- MIRBuilder.buildCopy(ValVReg, PhysReg);
+ if (ValSize == LocSize) {
+ MIRBuilder.buildCopy(ValVReg, PhysReg);
+ } else {
+ assert(ValSize < LocSize && "Extensions not supported");
+
+ // We cannot create a truncating copy, nor a trunc of a physical register.
+ // Therefore, we need to copy the content of the physical register into a
+ // virtual one and then truncate that.
+ auto PhysRegToVReg =
+ MRI.createGenericVirtualRegister(LLT::scalar(LocSize));
+ MIRBuilder.buildCopy(PhysRegToVReg, PhysReg);
+ MIRBuilder.buildTrunc(ValVReg, PhysRegToVReg);
+ }
}
unsigned assignCustomValue(const ARMCallLowering::ArgInfo &Arg,
MIRBuilder.buildLoad(ValVReg, Addr, *MMO);
}
+ void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
+ CCValAssign &VA) override {
+ markPhysRegUsed(PhysReg);
+ 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;
+ }
+ }
+ }
+
+ /// How the physical register gets marked varies between formal
+ /// parameters (it's a basic-block live-in), and a call instruction
+ /// (it's an implicit-def of the BL).
+ virtual void markPhysRegUsed(unsigned PhysReg) = 0;
+
protected:
const DataLayout &DL;
};
CCAssignFn *AssignFn)
: IncomingValueHandler(MIRBuilder, MRI, AssignFn) {}
- void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
- CCValAssign &VA) override {
+ void markPhysRegUsed(unsigned PhysReg) override {
MIRBuilder.getMBB().addLiveIn(PhysReg);
- MIRBuilder.buildCopy(ValVReg, PhysReg);
}
};
CCAssignFn *AssignFn, MachineInstrBuilder &MIB)
: IncomingValueHandler(MIRBuilder, MRI, AssignFn), MIB(MIB) {}
- void assignValueToReg(unsigned ValVReg, unsigned PhysReg,
- CCValAssign &VA) override {
+ void markPhysRegUsed(unsigned PhysReg) override {
MIB.addDef(PhysReg, RegState::Implicit);
- MIRBuilder.buildCopy(ValVReg, PhysReg);
}
protected:
; 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)
; 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: <unknown>:0:0: cannot select: G_STORE %vreg5, %vreg2; mem:ST4[%addr] GPR:%vreg5,%vreg2 (in function: pending_phis)
+; FALLBACK-WITH-REPORT-ERR: remark: <unknown>: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) {
}
; 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]]
}
; 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]]
}
; 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]]
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)
; 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
; 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)
define signext i1 @test_add_i1(i1 %x, i1 %y) {
; CHECK-LABEL: name: test_add_i1
; CHECK: liveins: %r0, %r1
-; CHECK-DAG: [[VREGX:%[0-9]+]](s1) = COPY %r0
-; CHECK-DAG: [[VREGY:%[0-9]+]](s1) = COPY %r1
+; CHECK-DAG: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[VREGX:%[0-9]+]](s1) = G_TRUNC [[VREGR0]]
+; CHECK-DAG: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[VREGY:%[0-9]+]](s1) = G_TRUNC [[VREGR1]]
; CHECK: [[SUM:%[0-9]+]](s1) = G_ADD [[VREGX]], [[VREGY]]
; CHECK: [[EXT:%[0-9]+]](s32) = G_SEXT [[SUM]]
; CHECK: %r0 = COPY [[EXT]](s32)
define i8 @test_add_i8(i8 %x, i8 %y) {
; CHECK-LABEL: name: test_add_i8
; CHECK: liveins: %r0, %r1
-; CHECK-DAG: [[VREGX:%[0-9]+]](s8) = COPY %r0
-; CHECK-DAG: [[VREGY:%[0-9]+]](s8) = COPY %r1
+; CHECK-DAG: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[VREGX:%[0-9]+]](s8) = G_TRUNC [[VREGR0]]
+; CHECK-DAG: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[VREGY:%[0-9]+]](s8) = G_TRUNC [[VREGR1]]
; CHECK: [[SUM:%[0-9]+]](s8) = G_ADD [[VREGX]], [[VREGY]]
-; CHECK: %r0 = COPY [[SUM]](s8)
+; CHECK: [[SUM_EXT:%[0-9]+]](s32) = G_ANYEXT [[SUM]]
+; CHECK: %r0 = COPY [[SUM_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%sum = add i8 %x, %y
define i8 @test_sub_i8(i8 %x, i8 %y) {
; CHECK-LABEL: name: test_sub_i8
; CHECK: liveins: %r0, %r1
-; CHECK-DAG: [[VREGX:%[0-9]+]](s8) = COPY %r0
-; CHECK-DAG: [[VREGY:%[0-9]+]](s8) = COPY %r1
+; CHECK-DAG: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[VREGX:%[0-9]+]](s8) = G_TRUNC [[VREGR0]]
+; CHECK-DAG: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[VREGY:%[0-9]+]](s8) = G_TRUNC [[VREGR1]]
; CHECK: [[RES:%[0-9]+]](s8) = G_SUB [[VREGX]], [[VREGY]]
-; CHECK: %r0 = COPY [[RES]](s8)
+; CHECK: [[RES_EXT:%[0-9]+]](s32) = G_ANYEXT [[RES]]
+; CHECK: %r0 = COPY [[RES_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%res = sub i8 %x, %y
define signext i8 @test_return_sext_i8(i8 %x) {
; CHECK-LABEL: name: test_return_sext_i8
; CHECK: liveins: %r0
-; CHECK: [[VREG:%[0-9]+]](s8) = COPY %r0
+; CHECK: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK: [[VREG:%[0-9]+]](s8) = G_TRUNC [[VREGR0]]
; CHECK: [[VREGEXT:%[0-9]+]](s32) = G_SEXT [[VREG]]
; CHECK: %r0 = COPY [[VREGEXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
define i16 @test_add_i16(i16 %x, i16 %y) {
; CHECK-LABEL: name: test_add_i16
; CHECK: liveins: %r0, %r1
-; CHECK-DAG: [[VREGX:%[0-9]+]](s16) = COPY %r0
-; CHECK-DAG: [[VREGY:%[0-9]+]](s16) = COPY %r1
+; CHECK-DAG: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[VREGX:%[0-9]+]](s16) = G_TRUNC [[VREGR0]]
+; CHECK-DAG: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[VREGY:%[0-9]+]](s16) = G_TRUNC [[VREGR1]]
; CHECK: [[SUM:%[0-9]+]](s16) = G_ADD [[VREGX]], [[VREGY]]
-; CHECK: %r0 = COPY [[SUM]](s16)
+; CHECK: [[SUM_EXT:%[0-9]+]](s32) = G_ANYEXT [[SUM]]
+; CHECK: %r0 = COPY [[SUM_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%sum = add i16 %x, %y
define i16 @test_sub_i16(i16 %x, i16 %y) {
; CHECK-LABEL: name: test_sub_i16
; CHECK: liveins: %r0, %r1
-; CHECK-DAG: [[VREGX:%[0-9]+]](s16) = COPY %r0
-; CHECK-DAG: [[VREGY:%[0-9]+]](s16) = COPY %r1
+; CHECK-DAG: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[VREGX:%[0-9]+]](s16) = G_TRUNC [[VREGR0]]
+; CHECK-DAG: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[VREGY:%[0-9]+]](s16) = G_TRUNC [[VREGR1]]
; CHECK: [[RES:%[0-9]+]](s16) = G_SUB [[VREGX]], [[VREGY]]
-; CHECK: %r0 = COPY [[RES]](s16)
+; CHECK: [[RES_EXT:%[0-9]+]](s32) = G_ANYEXT [[RES]]
+; CHECK: %r0 = COPY [[RES_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%res = sub i16 %x, %y
define zeroext i16 @test_return_zext_i16(i16 %x) {
; CHECK-LABEL: name: test_return_zext_i16
; CHECK: liveins: %r0
-; CHECK: [[VREG:%[0-9]+]](s16) = COPY %r0
+; CHECK: [[VREGR0:%[0-9]+]](s32) = COPY %r0
+; CHECK: [[VREG:%[0-9]+]](s16) = G_TRUNC [[VREGR0]]
; CHECK: [[VREGEXT:%[0-9]+]](s32) = G_ZEXT [[VREG]]
; CHECK: %r0 = COPY [[VREGEXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
; CHECK-DAG: id: [[P4:[0-9]]]{{.*}}offset: 0{{.*}}size: 1
; CHECK-DAG: id: [[P5:[0-9]]]{{.*}}offset: 4{{.*}}size: 2
; CHECK: liveins: %r0, %r1, %r2, %r3
-; CHECK: [[VREGP1:%[0-9]+]](s16) = COPY %r1
+; CHECK: [[VREGR1:%[0-9]+]](s32) = COPY %r1
+; CHECK: [[VREGP1:%[0-9]+]](s16) = G_TRUNC [[VREGR1]]
; CHECK: [[FIP5:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[P5]]
; CHECK: [[VREGP5EXT:%[0-9]+]](s32) = G_LOAD [[FIP5]](p0){{.*}}load 4
; CHECK: [[VREGP5:%[0-9]+]](s16) = G_TRUNC [[VREGP5EXT]]
; CHECK: [[SUM:%[0-9]+]](s16) = G_ADD [[VREGP1]], [[VREGP5]]
-; CHECK: %r0 = COPY [[SUM]]
+; CHECK: [[SUM_EXT:%[0-9]+]](s32) = G_ANYEXT [[SUM]]
+; CHECK: %r0 = COPY [[SUM_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%sum = add i16 %p1, %p5
; CHECK-DAG: id: [[P4:[0-9]]]{{.*}}offset: 0{{.*}}size: 1
; CHECK-DAG: id: [[P5:[0-9]]]{{.*}}offset: 4{{.*}}size: 2
; CHECK: liveins: %r0, %r1, %r2, %r3
-; CHECK: [[VREGP2:%[0-9]+]](s8) = COPY %r2
+; CHECK: [[VREGR2:%[0-9]+]](s32) = COPY %r2
+; CHECK: [[VREGP2:%[0-9]+]](s8) = G_TRUNC [[VREGR2]]
; CHECK: [[FIP4:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[P4]]
; CHECK: [[VREGP4EXT:%[0-9]+]](s32) = G_LOAD [[FIP4]](p0){{.*}}load 4
; CHECK: [[VREGP4:%[0-9]+]](s8) = G_TRUNC [[VREGP4EXT]]
; CHECK: [[SUM:%[0-9]+]](s8) = G_ADD [[VREGP2]], [[VREGP4]]
-; CHECK: %r0 = COPY [[SUM]]
+; CHECK: [[SUM_EXT:%[0-9]+]](s32) = G_ANYEXT [[SUM]]
+; CHECK: %r0 = COPY [[SUM_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%sum = add i8 %p2, %p4
; CHECK-DAG: id: [[P4:[0-9]]]{{.*}}offset: 0{{.*}}size: 1
; CHECK-DAG: id: [[P5:[0-9]]]{{.*}}offset: 4{{.*}}size: 2
; CHECK: liveins: %r0, %r1, %r2, %r3
-; CHECK: [[VREGP2:%[0-9]+]](s8) = COPY %r2
+; CHECK: [[VREGR2:%[0-9]+]](s32) = COPY %r2
+; CHECK: [[VREGP2:%[0-9]+]](s8) = G_TRUNC [[VREGR2]]
; CHECK: [[FIP4:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[P4]]
; CHECK: [[VREGP4:%[0-9]+]](s8) = G_LOAD [[FIP4]](p0){{.*}}load 1
; CHECK: [[SUM:%[0-9]+]](s8) = G_ADD [[VREGP2]], [[VREGP4]]
-; CHECK: %r0 = COPY [[SUM]]
+; CHECK: [[SUM_EXT:%[0-9]+]](s32) = G_ANYEXT [[SUM]]
+; CHECK: %r0 = COPY [[SUM_EXT]](s32)
; CHECK: BX_RET 14, _, implicit %r0
entry:
%sum = add i8 %p2, %p4
define arm_aapcscc signext i16 @test_call_ext_params(i8 %a, i16 %b, i1 %c) {
; CHECK-LABEL: name: test_call_ext_params
-; CHECK-DAG: [[AVREG:%[0-9]+]](s8) = COPY %r0
-; CHECK-DAG: [[BVREG:%[0-9]+]](s16) = COPY %r1
-; CHECK-DAG: [[CVREG:%[0-9]+]](s1) = COPY %r2
+; CHECK-DAG: [[R0VREG:%[0-9]+]](s32) = COPY %r0
+; CHECK-DAG: [[AVREG:%[0-9]+]](s8) = G_TRUNC [[R0VREG]]
+; CHECK-DAG: [[R1VREG:%[0-9]+]](s32) = COPY %r1
+; CHECK-DAG: [[BVREG:%[0-9]+]](s16) = G_TRUNC [[R1VREG]]
+; CHECK-DAG: [[R2VREG:%[0-9]+]](s32) = COPY %r2
+; CHECK-DAG: [[CVREG:%[0-9]+]](s1) = G_TRUNC [[R2VREG]]
; CHECK: ADJCALLSTACKDOWN 20, 0, 14, _, implicit-def %sp, implicit %sp
; CHECK: [[SEXTA:%[0-9]+]](s32) = G_SEXT [[AVREG]](s8)
; CHECK: %r0 = COPY [[SEXTA]]
; CHECK: [[ZEXTC:%[0-9]+]](s32) = G_ZEXT [[CVREG]]
; CHECK: G_STORE [[ZEXTC]](s32), [[FI5]](p0){{.*}}store 4
; CHECK: BLX @ext_target, csr_aapcs, implicit-def %lr, implicit %sp, implicit %r0, implicit %r1, implicit %r2, implicit %r3, implicit-def %r0
-; CHECK: [[RVREG:%[0-9]+]](s16) = COPY %r0
+; CHECK: [[R0VREG:%[0-9]+]](s32) = COPY %r0
+; CHECK: [[RVREG:%[0-9]+]](s16) = G_TRUNC [[R0VREG]]
; CHECK: ADJCALLSTACKUP 20, 0, 14, _, implicit-def %sp, implicit %sp
; CHECK: [[RExtVREG:%[0-9]+]](s32) = G_SEXT [[RVREG]]
; CHECK: %r0 = COPY [[RExtVREG]]
define i16 @test_add_i16(i16 %arg1, i16 %arg2) {
; X64-LABEL: test_add_i16:
; X64: # BB#0:
-; X64-NEXT: # kill: %DI<def> %DI<kill> %RDI<def>
-; X64-NEXT: # kill: %SI<def> %SI<kill> %RSI<def>
+; X64-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
+; X64-NEXT: # kill: %ESI<def> %ESI<kill> %RSI<def>
; X64-NEXT: leal (%rsi,%rdi), %eax
; X64-NEXT: # kill: %AX<def> %AX<kill> %EAX<kill>
; X64-NEXT: retq
; X32-NEXT: pushl %ebx
; X32-NEXT: .Lcfi7:
; X32-NEXT: .cfi_def_cfa_offset 8
-; X32-NEXT: subl $8, %esp
+; X32-NEXT: pushl %esi
; X32-NEXT: .Lcfi8:
-; X32-NEXT: .cfi_def_cfa_offset 16
+; X32-NEXT: .cfi_def_cfa_offset 12
+; X32-NEXT: pushl %eax
; X32-NEXT: .Lcfi9:
+; X32-NEXT: .cfi_def_cfa_offset 16
+; X32-NEXT: .Lcfi10:
+; X32-NEXT: .cfi_offset %esi, -12
+; X32-NEXT: .Lcfi11:
; X32-NEXT: .cfi_offset %ebx, -8
; X32-NEXT: movl 16(%esp), %eax
; X32-NEXT: movb (%eax), %bl
-; X32-NEXT: movb %bl, (%esp)
+; X32-NEXT: movzbl %bl, %esi
+; X32-NEXT: movl %esi, (%esp)
; X32-NEXT: calll take_char
; X32-NEXT: movsbl %bl, %eax
; X32-NEXT: movl %eax, (%esp)
; X32-NEXT: calll take_char
-; X32-NEXT: movzbl %bl, %eax
-; X32-NEXT: movl %eax, (%esp)
+; X32-NEXT: movl %esi, (%esp)
; X32-NEXT: calll take_char
-; X32-NEXT: addl $8, %esp
+; X32-NEXT: addl $4, %esp
+; X32-NEXT: popl %esi
; X32-NEXT: popl %ebx
; X32-NEXT: retl
;
; X64-NEXT: .cfi_def_cfa_offset 16
; X64-NEXT: .Lcfi7:
; X64-NEXT: .cfi_offset %rbx, -16
-; X64-NEXT: movb (%rdi), %bl
+; X64-NEXT: movb (%rdi), %al
+; X64-NEXT: movzbl %al, %ebx
; X64-NEXT: movl %ebx, %edi
; X64-NEXT: callq take_char
-; X64-NEXT: movsbl %bl, %ebx
-; X64-NEXT: movl %ebx, %edi
+; X64-NEXT: movsbl %bl, %edi
; X64-NEXT: callq take_char
-; X64-NEXT: movzbl %bl, %edi
+; X64-NEXT: movl %ebx, %edi
; X64-NEXT: callq take_char
; X64-NEXT: popq %rbx
; X64-NEXT: retq
; X32-LABEL: test_variadic_call_1:
; X32: # BB#0:
; X32-NEXT: subl $12, %esp
-; X32-NEXT: .Lcfi10:
+; X32-NEXT: .Lcfi12:
; X32-NEXT: .cfi_def_cfa_offset 16
; X32-NEXT: movl 16(%esp), %eax
; X32-NEXT: movl 20(%esp), %ecx
; X32-LABEL: test_variadic_call_2:
; X32: # BB#0:
; X32-NEXT: subl $12, %esp
-; X32-NEXT: .Lcfi11:
+; X32-NEXT: .Lcfi13:
; X32-NEXT: .cfi_def_cfa_offset 16
; X32-NEXT: movl 16(%esp), %eax
; X32-NEXT: movl 20(%esp), %ecx
define i64 @test_zext_i1(i8 %a) {
; X64-LABEL: test_zext_i1:
; X64: # BB#0:
-; X64-NEXT: # kill: %DIL<def> %DIL<kill> %RDI<def>
+; X64-NEXT: # kill: %EDI<def> %EDI<kill> %RDI<def>
; X64-NEXT: andq $1, %rdi
; X64-NEXT: movq %rdi, %rax
; X64-NEXT: retq
; X64-NEXT: isImmutable: true,
; X64: liveins: %ecx, %edi, %edx, %esi, %r8d, %r9d
-; X64: [[ARG1:%[0-9]+]](s8) = COPY %edi
-; X64-NEXT: %{{[0-9]+}}(s8) = COPY %esi
-; X64-NEXT: %{{[0-9]+}}(s8) = COPY %edx
-; X64-NEXT: %{{[0-9]+}}(s8) = COPY %ecx
-; X64-NEXT: %{{[0-9]+}}(s8) = COPY %r8d
-; X64-NEXT: %{{[0-9]+}}(s8) = COPY %r9d
+; X64: [[ARG1_TMP:%[0-9]+]](s32) = COPY %edi
+; X64: [[ARG1:%[0-9]+]](s8) = G_TRUNC [[ARG1_TMP]](s32)
+; X64-NEXT: %{{[0-9]+}}(s32) = COPY %esi
+; X64-NEXT: %{{[0-9]+}}(s8) = G_TRUNC %{{[0-9]+}}(s32)
+; X64-NEXT: %{{[0-9]+}}(s32) = COPY %edx
+; X64-NEXT: %{{[0-9]+}}(s8) = G_TRUNC %{{[0-9]+}}(s32)
+; X64-NEXT: %{{[0-9]+}}(s32) = COPY %ecx
+; X64-NEXT: %{{[0-9]+}}(s8) = G_TRUNC %{{[0-9]+}}(s32)
+; X64-NEXT: %{{[0-9]+}}(s32) = COPY %r8d
+; X64-NEXT: %{{[0-9]+}}(s8) = G_TRUNC %{{[0-9]+}}(s32)
+; X64-NEXT: %{{[0-9]+}}(s32) = COPY %r9d
+; X64-NEXT: %{{[0-9]+}}(s8) = G_TRUNC %{{[0-9]+}}(s32)
; X64-NEXT: [[ARG7_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK0]]
; X64-NEXT: [[ARG7:%[0-9]+]](s8) = G_LOAD [[ARG7_ADDR]](p0) :: (invariant load 1 from %fixed-stack.[[STACK0]], align 0)
; X64-NEXT: [[ARG8_ADDR:%[0-9]+]](p0) = G_FRAME_INDEX %fixed-stack.[[STACK8]]
; X32-NEXT: %3(p0) = COPY %esp
; X32-NEXT: %4(s32) = G_CONSTANT i32 0
; X32-NEXT: %5(p0) = G_GEP %3, %4(s32)
-; X32-NEXT: G_STORE %2(s8), %5(p0) :: (store 4 into stack, align 0)
+; X32-NEXT: %6(s32) = G_ANYEXT %2(s8)
+; X32-NEXT: G_STORE %6(s32), %5(p0) :: (store 4 into stack, align 0)
; X32-NEXT: CALLpcrel32 @take_char, csr_32, implicit %esp
; X32-NEXT: ADJCALLSTACKUP32 4, 0, implicit-def %esp, implicit-def %eflags, implicit %esp
; X32-NEXT: ADJCALLSTACKDOWN32 4, 0, 0, implicit-def %esp, implicit-def %eflags, implicit %esp
-; X32-NEXT: %6(p0) = COPY %esp
-; X32-NEXT: %7(s32) = G_CONSTANT i32 0
-; X32-NEXT: %8(p0) = G_GEP %6, %7(s32)
-; X32-NEXT: %9(s32) = G_SEXT %2(s8)
-; X32-NEXT: G_STORE %9(s32), %8(p0) :: (store 4 into stack, align 0)
+; X32-NEXT: %7(p0) = COPY %esp
+; X32-NEXT: %8(s32) = G_CONSTANT i32 0
+; X32-NEXT: %9(p0) = G_GEP %7, %8(s32)
+; X32-NEXT: %10(s32) = G_SEXT %2(s8)
+; X32-NEXT: G_STORE %10(s32), %9(p0) :: (store 4 into stack, align 0)
; X32-NEXT: CALLpcrel32 @take_char, csr_32, implicit %esp
; X32-NEXT: ADJCALLSTACKUP32 4, 0, implicit-def %esp, implicit-def %eflags, implicit %esp
; X32-NEXT: ADJCALLSTACKDOWN32 4, 0, 0, implicit-def %esp, implicit-def %eflags, implicit %esp
-; X32-NEXT: %10(p0) = COPY %esp
-; X32-NEXT: %11(s32) = G_CONSTANT i32 0
-; X32-NEXT: %12(p0) = G_GEP %10, %11(s32)
-; X32-NEXT: %13(s32) = G_ZEXT %2(s8)
-; X32-NEXT: G_STORE %13(s32), %12(p0) :: (store 4 into stack, align 0)
+; X32-NEXT: %11(p0) = COPY %esp
+; X32-NEXT: %12(s32) = G_CONSTANT i32 0
+; X32-NEXT: %13(p0) = G_GEP %11, %12(s32)
+; X32-NEXT: %14(s32) = G_ZEXT %2(s8)
+; X32-NEXT: G_STORE %14(s32), %13(p0) :: (store 4 into stack, align 0)
; X32-NEXT: CALLpcrel32 @take_char, csr_32, implicit %esp
; X32-NEXT: ADJCALLSTACKUP32 4, 0, implicit-def %esp, implicit-def %eflags, implicit %esp
; X32-NEXT: RET 0
; X64: %0(p0) = COPY %rdi
; X64-NEXT: %1(s8) = G_LOAD %0(p0) :: (load 1 from %ir.addr)
; X64-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
-; X64-NEXT: %edi = COPY %1(s8)
+; X64-NEXT: %2(s32) = G_ANYEXT %1(s8)
+; X64-NEXT: %edi = COPY %2(s32)
; X64-NEXT: CALL64pcrel32 @take_char, csr_64, implicit %rsp, implicit %edi
; X64-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
; X64-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
-; X64-NEXT: %2(s32) = G_SEXT %1(s8)
-; X64-NEXT: %edi = COPY %2(s32)
+; X64-NEXT: %3(s32) = G_SEXT %1(s8)
+; X64-NEXT: %edi = COPY %3(s32)
; X64-NEXT: CALL64pcrel32 @take_char, csr_64, implicit %rsp, implicit %edi
; X64-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
; X64-NEXT: ADJCALLSTACKDOWN64 0, 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
-; X64-NEXT: %3(s32) = G_ZEXT %1(s8)
-; X64-NEXT: %edi = COPY %3(s32)
+; X64-NEXT: %4(s32) = G_ZEXT %1(s8)
+; X64-NEXT: %edi = COPY %4(s32)
; X64-NEXT: CALL64pcrel32 @take_char, csr_64, implicit %rsp, implicit %edi
; X64-NEXT: ADJCALLSTACKUP64 0, 0, implicit-def %rsp, implicit-def %eflags, implicit %rsp
; X64-NEXT: RET 0