1; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -machine-combiner-verify-pattern-order=true | FileCheck %s 2; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mcpu=x86-64 -stop-after machine-combiner -machine-combiner-verify-pattern-order=true -o - | FileCheck %s --check-prefix=DEAD 3 4; Verify that integer multiplies are reassociated. The first multiply in 5; each test should be independent of the result of the preceding add (lea). 6 7; TODO: This test does not actually test i16 machine instruction reassociation 8; because the operands are being promoted to i32 types. 9 10define i16 @reassociate_muls_i16(i16 %x0, i16 %x1, i16 %x2, i16 %x3) { 11; CHECK-LABEL: reassociate_muls_i16: 12; CHECK: # %bb.0: 13; CHECK-NEXT: # kill 14; CHECK-NEXT: # kill 15; CHECK-NEXT: leal (%rdi,%rsi), %eax 16; CHECK-NEXT: imull %ecx, %edx 17; CHECK-NEXT: imull %edx, %eax 18; CHECK-NEXT: # kill 19; CHECK-NEXT: retq 20 %t0 = add i16 %x0, %x1 21 %t1 = mul i16 %x2, %t0 22 %t2 = mul i16 %x3, %t1 23 ret i16 %t2 24} 25 26define i32 @reassociate_muls_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 27; CHECK-LABEL: reassociate_muls_i32: 28; CHECK: # %bb.0: 29; CHECK-NEXT: # kill 30; CHECK-NEXT: # kill 31; CHECK-NEXT: leal (%rdi,%rsi), %eax 32; CHECK-NEXT: imull %ecx, %edx 33; CHECK-NEXT: imull %edx, %eax 34; CHECK-NEXT: retq 35 36; DEAD: ADD32rr 37; DEAD-NEXT: IMUL32rr{{.*}}implicit-def dead $eflags 38; DEAD-NEXT: IMUL32rr{{.*}}implicit-def dead $eflags 39 40 %t0 = add i32 %x0, %x1 41 %t1 = mul i32 %x2, %t0 42 %t2 = mul i32 %x3, %t1 43 ret i32 %t2 44} 45 46define i64 @reassociate_muls_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 47; CHECK-LABEL: reassociate_muls_i64: 48; CHECK: # %bb.0: 49; CHECK-NEXT: leaq (%rdi,%rsi), %rax 50; CHECK-NEXT: imulq %rcx, %rdx 51; CHECK-NEXT: imulq %rdx, %rax 52; CHECK-NEXT: retq 53 %t0 = add i64 %x0, %x1 54 %t1 = mul i64 %x2, %t0 55 %t2 = mul i64 %x3, %t1 56 ret i64 %t2 57} 58 59; Verify that integer 'ands' are reassociated. The first 'and' in 60; each test should be independent of the result of the preceding sub. 61 62define i8 @reassociate_ands_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 63; CHECK-LABEL: reassociate_ands_i8: 64; CHECK: # %bb.0: 65; CHECK-NEXT: subb %sil, %dil 66; CHECK-NEXT: andb %cl, %dl 67; CHECK-NEXT: andb %dil, %dl 68; CHECK-NEXT: movl %edx, %eax 69; CHECK-NEXT: retq 70 %t0 = sub i8 %x0, %x1 71 %t1 = and i8 %x2, %t0 72 %t2 = and i8 %x3, %t1 73 ret i8 %t2 74} 75 76; TODO: No way to test i16? These appear to always get promoted to i32. 77 78define i32 @reassociate_ands_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 79; CHECK-LABEL: reassociate_ands_i32: 80; CHECK: # %bb.0: 81; CHECK-NEXT: subl %esi, %edi 82; CHECK-NEXT: andl %ecx, %edx 83; CHECK-NEXT: andl %edi, %edx 84; CHECK-NEXT: movl %edx, %eax 85; CHECK-NEXT: retq 86 %t0 = sub i32 %x0, %x1 87 %t1 = and i32 %x2, %t0 88 %t2 = and i32 %x3, %t1 89 ret i32 %t2 90} 91 92define i64 @reassociate_ands_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 93; CHECK-LABEL: reassociate_ands_i64: 94; CHECK: # %bb.0: 95; CHECK-NEXT: subq %rsi, %rdi 96; CHECK-NEXT: andq %rcx, %rdx 97; CHECK-NEXT: andq %rdi, %rdx 98; CHECK-NEXT: movq %rdx, %rax 99; CHECK-NEXT: retq 100 %t0 = sub i64 %x0, %x1 101 %t1 = and i64 %x2, %t0 102 %t2 = and i64 %x3, %t1 103 ret i64 %t2 104} 105 106; Verify that integer 'ors' are reassociated. The first 'or' in 107; each test should be independent of the result of the preceding sub. 108 109define i8 @reassociate_ors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 110; CHECK-LABEL: reassociate_ors_i8: 111; CHECK: # %bb.0: 112; CHECK-NEXT: subb %sil, %dil 113; CHECK-NEXT: orb %cl, %dl 114; CHECK-NEXT: orb %dil, %dl 115; CHECK-NEXT: movl %edx, %eax 116; CHECK-NEXT: retq 117 %t0 = sub i8 %x0, %x1 118 %t1 = or i8 %x2, %t0 119 %t2 = or i8 %x3, %t1 120 ret i8 %t2 121} 122 123; TODO: No way to test i16? These appear to always get promoted to i32. 124 125define i32 @reassociate_ors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 126; CHECK-LABEL: reassociate_ors_i32: 127; CHECK: # %bb.0: 128; CHECK-NEXT: subl %esi, %edi 129; CHECK-NEXT: orl %ecx, %edx 130; CHECK-NEXT: orl %edi, %edx 131; CHECK-NEXT: movl %edx, %eax 132; CHECK-NEXT: retq 133 %t0 = sub i32 %x0, %x1 134 %t1 = or i32 %x2, %t0 135 %t2 = or i32 %x3, %t1 136 ret i32 %t2 137} 138 139define i64 @reassociate_ors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 140; CHECK-LABEL: reassociate_ors_i64: 141; CHECK: # %bb.0: 142; CHECK-NEXT: subq %rsi, %rdi 143; CHECK-NEXT: orq %rcx, %rdx 144; CHECK-NEXT: orq %rdi, %rdx 145; CHECK-NEXT: movq %rdx, %rax 146; CHECK-NEXT: retq 147 %t0 = sub i64 %x0, %x1 148 %t1 = or i64 %x2, %t0 149 %t2 = or i64 %x3, %t1 150 ret i64 %t2 151} 152 153; Verify that integer 'xors' are reassociated. The first 'xor' in 154; each test should be independent of the result of the preceding sub. 155 156define i8 @reassociate_xors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 157; CHECK-LABEL: reassociate_xors_i8: 158; CHECK: # %bb.0: 159; CHECK-NEXT: subb %sil, %dil 160; CHECK-NEXT: xorb %cl, %dl 161; CHECK-NEXT: xorb %dil, %dl 162; CHECK-NEXT: movl %edx, %eax 163; CHECK-NEXT: retq 164 %t0 = sub i8 %x0, %x1 165 %t1 = xor i8 %x2, %t0 166 %t2 = xor i8 %x3, %t1 167 ret i8 %t2 168} 169 170; TODO: No way to test i16? These appear to always get promoted to i32. 171 172define i32 @reassociate_xors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 173; CHECK-LABEL: reassociate_xors_i32: 174; CHECK: # %bb.0: 175; CHECK-NEXT: subl %esi, %edi 176; CHECK-NEXT: xorl %ecx, %edx 177; CHECK-NEXT: xorl %edi, %edx 178; CHECK-NEXT: movl %edx, %eax 179; CHECK-NEXT: retq 180 %t0 = sub i32 %x0, %x1 181 %t1 = xor i32 %x2, %t0 182 %t2 = xor i32 %x3, %t1 183 ret i32 %t2 184} 185 186define i64 @reassociate_xors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 187; CHECK-LABEL: reassociate_xors_i64: 188; CHECK: # %bb.0: 189; CHECK-NEXT: subq %rsi, %rdi 190; CHECK-NEXT: xorq %rcx, %rdx 191; CHECK-NEXT: xorq %rdi, %rdx 192; CHECK-NEXT: movq %rdx, %rax 193; CHECK-NEXT: retq 194 %t0 = sub i64 %x0, %x1 195 %t1 = xor i64 %x2, %t0 196 %t2 = xor i64 %x3, %t1 197 ret i64 %t2 198} 199 200