mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
implement an instcombine xform that canonicalizes casts outside of and-with-constant operations.
This fixes rdar://8808586 which observed that we used to compile: union xy { struct x { _Bool b[15]; } x; __attribute__((packed)) struct y { __attribute__((packed)) unsigned long b0to7; __attribute__((packed)) unsigned int b8to11; __attribute__((packed)) unsigned short b12to13; __attribute__((packed)) unsigned char b14; } y; }; struct x foo(union xy *xy) { return xy->x; } into: _foo: ## @foo movq (%rdi), %rax movabsq $1095216660480, %rcx ## imm = 0xFF00000000 andq %rax, %rcx movabsq $-72057594037927936, %rdx ## imm = 0xFF00000000000000 andq %rax, %rdx movzbl %al, %esi orq %rdx, %rsi movq %rax, %rdx andq $65280, %rdx ## imm = 0xFF00 orq %rsi, %rdx movq %rax, %rsi andq $16711680, %rsi ## imm = 0xFF0000 orq %rdx, %rsi movl %eax, %edx andl $-16777216, %edx ## imm = 0xFFFFFFFFFF000000 orq %rsi, %rdx orq %rcx, %rdx movabsq $280375465082880, %rcx ## imm = 0xFF0000000000 movq %rax, %rsi andq %rcx, %rsi orq %rdx, %rsi movabsq $71776119061217280, %r8 ## imm = 0xFF000000000000 andq %r8, %rax orq %rsi, %rax movzwl 12(%rdi), %edx movzbl 14(%rdi), %esi shlq $16, %rsi orl %edx, %esi movq %rsi, %r9 shlq $32, %r9 movl 8(%rdi), %edx orq %r9, %rdx andq %rdx, %rcx movzbl %sil, %esi shlq $32, %rsi orq %rcx, %rsi movl %edx, %ecx andl $-16777216, %ecx ## imm = 0xFFFFFFFFFF000000 orq %rsi, %rcx movq %rdx, %rsi andq $16711680, %rsi ## imm = 0xFF0000 orq %rcx, %rsi movq %rdx, %rcx andq $65280, %rcx ## imm = 0xFF00 orq %rsi, %rcx movzbl %dl, %esi orq %rcx, %rsi andq %r8, %rdx orq %rsi, %rdx ret We now compile this into: _foo: ## @foo ## BB#0: ## %entry movzwl 12(%rdi), %eax movzbl 14(%rdi), %ecx shlq $16, %rcx orl %eax, %ecx shlq $32, %rcx movl 8(%rdi), %edx orq %rcx, %rdx movq (%rdi), %rax ret A small improvement :-) llvm-svn: 123520
This commit is contained in:
parent
089d215cb3
commit
74ed5d30ca
@ -462,8 +462,8 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
|
||||
|
||||
// Transform trunc(lshr (zext A), Cst) to eliminate one type conversion.
|
||||
Value *A = 0; ConstantInt *Cst = 0;
|
||||
if (match(Src, m_LShr(m_ZExt(m_Value(A)), m_ConstantInt(Cst))) &&
|
||||
Src->hasOneUse()) {
|
||||
if (Src->hasOneUse() &&
|
||||
match(Src, m_LShr(m_ZExt(m_Value(A)), m_ConstantInt(Cst)))) {
|
||||
// We have three types to worry about here, the type of A, the source of
|
||||
// the truncate (MidSize), and the destination of the truncate. We know that
|
||||
// ASize < MidSize and MidSize > ResultSize, but don't know the relation
|
||||
@ -482,6 +482,16 @@ Instruction *InstCombiner::visitTrunc(TruncInst &CI) {
|
||||
Shift->takeName(Src);
|
||||
return CastInst::CreateIntegerCast(Shift, CI.getType(), false);
|
||||
}
|
||||
|
||||
// Transform "trunc (and X, cst)" -> "and (trunc X), cst" so long as the dest
|
||||
// type isn't non-native.
|
||||
if (Src->hasOneUse() && isa<IntegerType>(Src->getType()) &&
|
||||
ShouldChangeType(Src->getType(), CI.getType()) &&
|
||||
match(Src, m_And(m_Value(A), m_ConstantInt(Cst)))) {
|
||||
Value *NewTrunc = Builder->CreateTrunc(A, CI.getType(), A->getName()+".tr");
|
||||
return BinaryOperator::CreateAnd(NewTrunc,
|
||||
ConstantExpr::getTrunc(Cst, CI.getType()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -97,3 +97,23 @@ define i64 @test8(i32 %A, i32 %B) {
|
||||
; CHECK: ret i64 %ins35
|
||||
}
|
||||
|
||||
define i8 @test9(i32 %X) {
|
||||
%Y = and i32 %X, 42
|
||||
%Z = trunc i32 %Y to i8
|
||||
ret i8 %Z
|
||||
; CHECK: @test9
|
||||
; CHECK: trunc
|
||||
; CHECK: and
|
||||
; CHECK: ret
|
||||
}
|
||||
|
||||
; rdar://8808586
|
||||
define i8 @test10(i32 %X) {
|
||||
%Y = trunc i32 %X to i8
|
||||
%Z = and i8 %Y, 42
|
||||
ret i8 %Z
|
||||
; CHECK: @test10
|
||||
; CHECK: trunc
|
||||
; CHECK: and
|
||||
; CHECK: ret
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user