Commit fbdd2440 by Jan Voung

Factor out legalization of undef, and handle more cases for ARM.

By factoring out legalizeUndef(), we can use the same logic in prelowerPhis which may help if we ever change the value used (though if we switch from zero-ing out regs to using uninitialized regs, it'll take more work -- e.g., can't return a 64-bit reg). For x86, use legalizeUndef where it's clear that the value is immediately fed to loOperand/hiOperand then another legalize() call. Otherwise, leave the general X = legalize(X); alone where the code is counting on that being the sole legalization. For x86 legalize(const64) is a pass-through, which can then be passed to loOperand/hiOperand nicely. However, for ARM, legalize(const64) may end up trying to copy the const64 to a register, but we don't have 64-bit registers. Instead do legalizeUndef(X) where x86 would have just done legalize(X). This happens to work because legalizeUndef doesn't try to copy to reg, and we immediately pass the result to loOperand/hiOperand() which then passes the result to a real legalization call. Add a few more undef tests. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4076 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1233903002 .
parent 728c1d40
......@@ -146,6 +146,7 @@ protected:
Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
int32_t RegNum = Variable::NoRegister);
Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
OperandARM32Mem *formMemoryOperand(Operand *Ptr, Type Ty);
Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
......
......@@ -230,6 +230,7 @@ protected:
Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
int32_t RegNum = Variable::NoRegister);
Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
Operand *legalizeUndef(Operand *From, int32_t RegNum = Variable::NoRegister);
/// Legalize the first source operand for use in the cmp instruction.
Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
/// Turn a pointer operand into a memory operand that can be
......
......@@ -109,6 +109,17 @@ entry:
; CHECK: cmovl
; CHECK: cmovl
define i64 @fold_cmp_select_64_undef(i64 %arg1) {
entry:
%arg1_trunc = trunc i64 %arg1 to i32
%cmp1 = icmp slt i32 undef, %arg1_trunc
%result = select i1 %cmp1, i64 %arg1, i64 undef
ret i64 %result
}
; CHECK-LABEL: fold_cmp_select_64_undef
; CHECK: cmp
; CHECK: cmovl
; CHECK: cmovl
; Cmp/select folding with intervening instructions.
define i32 @fold_cmp_select_intervening_insts(i32 %arg1, i32 %arg2) {
......
......@@ -771,6 +771,16 @@ entry:
; need to be reshuffled via movs. The next test stores the result
; somewhere, so in that case they do need to be mov'ed.
define i64 @test_atomic_cmpxchg_64_undef(i32 %iptr, i64 %desired) {
entry:
%ptr = inttoptr i32 %iptr to i64*
%old = call i64 @llvm.nacl.atomic.cmpxchg.i64(i64* %ptr, i64 undef,
i64 %desired, i32 6, i32 6)
ret i64 %old
}
; CHECK-LABEL: test_atomic_cmpxchg_64_undef
; CHECK: lock cmpxchg8b QWORD PTR [e{{.[^x]}}+0x0]
; Test a case where %old really does need to be copied out of edx:eax.
define void @test_atomic_cmpxchg_64_store(i32 %ret_iptr, i32 %iptr, i64 %expected, i64 %desired) {
entry:
......
......@@ -416,6 +416,18 @@ entry:
; ARM32: rev
; ARM32: rev
define i64 @test_bswap_64_undef() {
entry:
%r = call i64 @llvm.bswap.i64(i64 undef)
ret i64 %r
}
; CHECK-LABEL: test_bswap_64_undef
; CHECK: bswap e{{.*}}
; CHECK: bswap e{{.*}}
; ARM32-LABEL: test_bswap_64
; ARM32: rev
; ARM32: rev
define i32 @test_ctlz_32(i32 %x) {
entry:
%r = call i32 @llvm.ctlz.i32(i32 %x, i1 false)
......
......@@ -130,3 +130,15 @@ entry:
}
; CHECK-LABEL: no_rmw_sub_i32_var
; CHECK: sub e{{ax|bx|cx|dx|bp|di|si}},DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}]
define internal void @rmw_add_i64_undef(i32 %addr_arg) {
entry:
%addr = inttoptr i32 %addr_arg to i64*
%val = load i64, i64* %addr, align 1
%rmw = add i64 %val, undef
store i64 %rmw, i64* %addr, align 1
ret void
}
; CHECK-LABEL: rmw_add_i64_undef
; CHECK: add DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}],0x0
; CHECK: adc DWORD PTR [e{{ax|bx|cx|dx|bp|di|si}}+0x4],0x0
......@@ -147,3 +147,18 @@ sw.default:
; ARM32-NEXT: beq [[ADDR:[0-9a-f]+]]
; ARM32-NEXT: b [[ADDR]]
define i32 @testSwitchUndef64() {
entry:
switch i64 undef, label %sw.default [
i64 1, label %sw.default
]
sw.default:
ret i32 20
}
; CHECK-LABEL: testSwitchUndef64
; CHECK: mov {{.*}},0x0
; CHECK: mov {{.*}},0x0
; ARM32-LABEL: testSwitchUndef64
; ARM32: movw {{.*}}, #0
; ARM32: movw {{.*}}, #0
......@@ -25,6 +25,15 @@ entry:
; CHECK: ret
}
define i32 @trunc_undef_i64() {
entry:
%ret = trunc i64 undef to i32
ret i32 %ret
; CHECK-LABEL: trunc_undef_i64
; CHECK: mov eax,0x0
; CHECK: ret
}
define float @undef_float() {
entry:
ret float undef
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment