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: movl %edx, %eax 66; CHECK-NEXT: subb %sil, %dil 67; CHECK-NEXT: andb %cl, %al 68; CHECK-NEXT: andb %dil, %al 69; CHECK-NEXT: # kill 70; CHECK-NEXT: retq 71 %t0 = sub i8 %x0, %x1 72 %t1 = and i8 %x2, %t0 73 %t2 = and i8 %x3, %t1 74 ret i8 %t2 75} 76 77; TODO: No way to test i16? These appear to always get promoted to i32. 78 79define i32 @reassociate_ands_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 80; CHECK-LABEL: reassociate_ands_i32: 81; CHECK: # %bb.0: 82; CHECK-NEXT: movl %edx, %eax 83; CHECK-NEXT: subl %esi, %edi 84; CHECK-NEXT: andl %ecx, %eax 85; CHECK-NEXT: andl %edi, %eax 86; CHECK-NEXT: retq 87 %t0 = sub i32 %x0, %x1 88 %t1 = and i32 %x2, %t0 89 %t2 = and i32 %x3, %t1 90 ret i32 %t2 91} 92 93define i64 @reassociate_ands_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 94; CHECK-LABEL: reassociate_ands_i64: 95; CHECK: # %bb.0: 96; CHECK-NEXT: movq %rdx, %rax 97; CHECK-NEXT: subq %rsi, %rdi 98; CHECK-NEXT: andq %rcx, %rax 99; CHECK-NEXT: andq %rdi, %rax 100; CHECK-NEXT: retq 101 %t0 = sub i64 %x0, %x1 102 %t1 = and i64 %x2, %t0 103 %t2 = and i64 %x3, %t1 104 ret i64 %t2 105} 106 107; Verify that integer 'ors' are reassociated. The first 'or' in 108; each test should be independent of the result of the preceding sub. 109 110define i8 @reassociate_ors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 111; CHECK-LABEL: reassociate_ors_i8: 112; CHECK: # %bb.0: 113; CHECK-NEXT: movl %edx, %eax 114; CHECK-NEXT: subb %sil, %dil 115; CHECK-NEXT: orb %cl, %al 116; CHECK-NEXT: orb %dil, %al 117; CHECK-NEXT: # kill 118; CHECK-NEXT: retq 119 %t0 = sub i8 %x0, %x1 120 %t1 = or i8 %x2, %t0 121 %t2 = or i8 %x3, %t1 122 ret i8 %t2 123} 124 125; TODO: No way to test i16? These appear to always get promoted to i32. 126 127define i32 @reassociate_ors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 128; CHECK-LABEL: reassociate_ors_i32: 129; CHECK: # %bb.0: 130; CHECK-NEXT: movl %edx, %eax 131; CHECK-NEXT: subl %esi, %edi 132; CHECK-NEXT: orl %ecx, %eax 133; CHECK-NEXT: orl %edi, %eax 134; CHECK-NEXT: retq 135 %t0 = sub i32 %x0, %x1 136 %t1 = or i32 %x2, %t0 137 %t2 = or i32 %x3, %t1 138 ret i32 %t2 139} 140 141define i64 @reassociate_ors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 142; CHECK-LABEL: reassociate_ors_i64: 143; CHECK: # %bb.0: 144; CHECK-NEXT: movq %rdx, %rax 145; CHECK-NEXT: subq %rsi, %rdi 146; CHECK-NEXT: orq %rcx, %rax 147; CHECK-NEXT: orq %rdi, %rax 148; CHECK-NEXT: retq 149 %t0 = sub i64 %x0, %x1 150 %t1 = or i64 %x2, %t0 151 %t2 = or i64 %x3, %t1 152 ret i64 %t2 153} 154 155; Verify that integer 'xors' are reassociated. The first 'xor' in 156; each test should be independent of the result of the preceding sub. 157 158define i8 @reassociate_xors_i8(i8 %x0, i8 %x1, i8 %x2, i8 %x3) { 159; CHECK-LABEL: reassociate_xors_i8: 160; CHECK: # %bb.0: 161; CHECK-NEXT: movl %edx, %eax 162; CHECK-NEXT: subb %sil, %dil 163; CHECK-NEXT: xorb %cl, %al 164; CHECK-NEXT: xorb %dil, %al 165; CHECK-NEXT: # kill 166; CHECK-NEXT: retq 167 %t0 = sub i8 %x0, %x1 168 %t1 = xor i8 %x2, %t0 169 %t2 = xor i8 %x3, %t1 170 ret i8 %t2 171} 172 173; TODO: No way to test i16? These appear to always get promoted to i32. 174 175define i32 @reassociate_xors_i32(i32 %x0, i32 %x1, i32 %x2, i32 %x3) { 176; CHECK-LABEL: reassociate_xors_i32: 177; CHECK: # %bb.0: 178; CHECK-NEXT: movl %edx, %eax 179; CHECK-NEXT: subl %esi, %edi 180; CHECK-NEXT: xorl %ecx, %eax 181; CHECK-NEXT: xorl %edi, %eax 182; CHECK-NEXT: retq 183 %t0 = sub i32 %x0, %x1 184 %t1 = xor i32 %x2, %t0 185 %t2 = xor i32 %x3, %t1 186 ret i32 %t2 187} 188 189define i64 @reassociate_xors_i64(i64 %x0, i64 %x1, i64 %x2, i64 %x3) { 190; CHECK-LABEL: reassociate_xors_i64: 191; CHECK: # %bb.0: 192; CHECK-NEXT: movq %rdx, %rax 193; CHECK-NEXT: subq %rsi, %rdi 194; CHECK-NEXT: xorq %rcx, %rax 195; CHECK-NEXT: xorq %rdi, %rax 196; CHECK-NEXT: retq 197 %t0 = sub i64 %x0, %x1 198 %t1 = xor i64 %x2, %t0 199 %t2 = xor i64 %x3, %t1 200 ret i64 %t2 201} 202 203