224 lines
6.3 KiB
Plaintext
224 lines
6.3 KiB
Plaintext
|
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||
|
#
|
||
|
# Check that we can fold (x & mask) -> x when (x & mask) is known to equal x.
|
||
|
#
|
||
|
# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
|
||
|
|
||
|
---
|
||
|
name: remove_and_with_one_bit
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1
|
||
|
; G_ICMP produces a single bit. The mask is 1.
|
||
|
;
|
||
|
; cmp = 000...0?
|
||
|
; mask = 000...01
|
||
|
; cmp & mask = 000...0?
|
||
|
;
|
||
|
; Remove the G_AND.
|
||
|
;
|
||
|
; CHECK-LABEL: name: remove_and_with_one_bit
|
||
|
; CHECK: liveins: $w0, $w1
|
||
|
; CHECK: %x:_(s32) = COPY $w0
|
||
|
; CHECK: %y:_(s32) = COPY $w1
|
||
|
; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
|
||
|
; CHECK: $w0 = COPY %cmp(s32)
|
||
|
; CHECK: RET_ReallyLR implicit $w0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
|
||
|
%mask:_(s32) = G_CONSTANT i32 1
|
||
|
%and:_(s32) = G_AND %cmp(s32), %mask
|
||
|
$w0 = COPY %and(s32)
|
||
|
RET_ReallyLR implicit $w0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: remove_and_all_ones_mask
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; -1 is all ones. Therefore z & -1 = z. Remove the G_AND.
|
||
|
;
|
||
|
; CHECK-LABEL: name: remove_and_all_ones_mask
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = COPY $w2
|
||
|
; CHECK: $w0 = COPY %z(s32)
|
||
|
; CHECK: RET_ReallyLR implicit $w0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = COPY $w2
|
||
|
%mask:_(s32) = G_CONSTANT i32 -1
|
||
|
%and:_(s32) = G_AND %z(s32), %mask
|
||
|
$w0 = COPY %and(s32)
|
||
|
RET_ReallyLR implicit $w0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: remove_and_all_ones_zext
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; %z is a s32, so it can be at most the all-ones value on 32 bits.
|
||
|
; In decimal this is 4294967295. Any zero-extension of %z is at most this
|
||
|
; value.
|
||
|
;
|
||
|
; Therefore, zext(z) & 4294967295 == z. Remove the G_AND.
|
||
|
;
|
||
|
; CHECK-LABEL: name: remove_and_all_ones_zext
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = COPY $w2
|
||
|
; CHECK: %ext:_(s64) = G_ZEXT %z(s32)
|
||
|
; CHECK: $x0 = COPY %ext(s64)
|
||
|
; CHECK: RET_ReallyLR implicit $x0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = COPY $w2
|
||
|
%ext:_(s64) = G_ZEXT %z
|
||
|
%mask:_(s64) = G_CONSTANT i64 4294967295
|
||
|
%and:_(s64) = G_AND %ext(s64), %mask
|
||
|
$x0 = COPY %and(s64)
|
||
|
RET_ReallyLR implicit $x0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: remove_and_all_ones_anyext
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; This is the same as the zext case.
|
||
|
;
|
||
|
; CHECK-LABEL: name: remove_and_all_ones_anyext
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = COPY $w2
|
||
|
; CHECK: %ext:_(s64) = G_ZEXT %z(s32)
|
||
|
; CHECK: $x0 = COPY %ext(s64)
|
||
|
; CHECK: RET_ReallyLR implicit $x0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = COPY $w2
|
||
|
%ext:_(s64) = G_ZEXT %z
|
||
|
%mask:_(s64) = G_CONSTANT i64 4294967295
|
||
|
%and:_(s64) = G_AND %ext(s64), %mask
|
||
|
$x0 = COPY %and(s64)
|
||
|
RET_ReallyLR implicit $x0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: dont_remove_all_ones_sext
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; We don't know if the sign bit is set on %z. So, the value in %ext may have
|
||
|
; higher bits set than 4294967295.
|
||
|
;
|
||
|
; CHECK-LABEL: name: dont_remove_all_ones_sext
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = COPY $w2
|
||
|
; CHECK: %ext:_(s64) = G_SEXT %z(s32)
|
||
|
; CHECK: %mask:_(s64) = G_CONSTANT i64 4294967295
|
||
|
; CHECK: %and:_(s64) = G_AND %ext, %mask
|
||
|
; CHECK: $x0 = COPY %and(s64)
|
||
|
; CHECK: RET_ReallyLR implicit $x0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = COPY $w2
|
||
|
%ext:_(s64) = G_SEXT %z
|
||
|
%mask:_(s64) = G_CONSTANT i64 4294967295
|
||
|
%and:_(s64) = G_AND %ext(s64), %mask
|
||
|
$x0 = COPY %and(s64)
|
||
|
RET_ReallyLR implicit $x0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: remove_and_positive_constant_sext
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; We know the sign bit is not set on %z. Therefore,
|
||
|
;
|
||
|
; z = ext = 42 = 000...0101010
|
||
|
; mask = 0000...0111111
|
||
|
;
|
||
|
; So z & mask == z
|
||
|
; CHECK-LABEL: name: remove_and_positive_constant_sext
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = G_CONSTANT i32 42
|
||
|
; CHECK: %ext:_(s64) = G_SEXT %z(s32)
|
||
|
; CHECK: $x0 = COPY %ext(s64)
|
||
|
; CHECK: RET_ReallyLR implicit $x0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = G_CONSTANT i32 42
|
||
|
%ext:_(s64) = G_SEXT %z
|
||
|
%mask:_(s64) = G_CONSTANT i64 63
|
||
|
%and:_(s64) = G_AND %ext(s64), %mask
|
||
|
$x0 = COPY %and(s64)
|
||
|
RET_ReallyLR implicit $x0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: not_a_mask
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1
|
||
|
; 6 is not a mask, so we should still have the G_AND.
|
||
|
;
|
||
|
; CHECK-LABEL: name: not_a_mask
|
||
|
; CHECK: liveins: $w0, $w1
|
||
|
; CHECK: %x:_(s32) = COPY $w0
|
||
|
; CHECK: %y:_(s32) = COPY $w1
|
||
|
; CHECK: %cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
|
||
|
; CHECK: %mask:_(s32) = G_CONSTANT i32 6
|
||
|
; CHECK: %and:_(s32) = G_AND %cmp, %mask
|
||
|
; CHECK: $w0 = COPY %and(s32)
|
||
|
; CHECK: RET_ReallyLR implicit $w0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%cmp:_(s32) = G_ICMP intpred(eq), %x(s32), %y
|
||
|
%mask:_(s32) = G_CONSTANT i32 6
|
||
|
%and:_(s32) = G_AND %cmp(s32), %mask
|
||
|
$w0 = COPY %and(s32)
|
||
|
RET_ReallyLR implicit $w0
|
||
|
|
||
|
...
|
||
|
---
|
||
|
name: unknown_val
|
||
|
legalized: true
|
||
|
tracksRegLiveness: true
|
||
|
body: |
|
||
|
bb.0:
|
||
|
liveins: $w0, $w1, $w2
|
||
|
; We don't know what's in $w2, so we can't remove the G_AND without a mask
|
||
|
; that fills every bit in the type.
|
||
|
;
|
||
|
; CHECK-LABEL: name: unknown_val
|
||
|
; CHECK: liveins: $w0, $w1, $w2
|
||
|
; CHECK: %z:_(s32) = COPY $w2
|
||
|
; CHECK: %one:_(s32) = G_CONSTANT i32 32
|
||
|
; CHECK: %and:_(s32) = G_AND %z, %one
|
||
|
; CHECK: $w0 = COPY %and(s32)
|
||
|
; CHECK: RET_ReallyLR implicit $w0
|
||
|
%x:_(s32) = COPY $w0
|
||
|
%y:_(s32) = COPY $w1
|
||
|
%z:_(s32) = COPY $w2
|
||
|
%one:_(s32) = G_CONSTANT i32 32
|
||
|
%and:_(s32) = G_AND %z(s32), %one
|
||
|
$w0 = COPY %and(s32)
|
||
|
RET_ReallyLR implicit $w0
|
||
|
...
|