From: Sanjay Patel Date: Sat, 14 Apr 2018 13:39:02 +0000 (+0000) Subject: [InstCombine] add shift+logic tests (PR37098); NFC X-Git-Tag: llvmorg-7.0.0-rc1~8151 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=713f09d0149bc62919fd93d013c477db096885b6;p=platform%2Fupstream%2Fllvm.git [InstCombine] add shift+logic tests (PR37098); NFC It debateable whether instcombine should be in the business of reassociation, but it is currently. These tests and PR37098 demonstrate a missing ability to do a simple reassociation that allows eliminating shifts. If we decide that functionality belongs somewhere else, then we should still have some tests to show that we've intentionally limited instcombine to *not* include this ability. llvm-svn: 330086 --- diff --git a/llvm/test/Transforms/InstCombine/and-xor-or.ll b/llvm/test/Transforms/InstCombine/and-xor-or.ll index ec36d13..e4495fa 100644 --- a/llvm/test/Transforms/InstCombine/and-xor-or.ll +++ b/llvm/test/Transforms/InstCombine/and-xor-or.ll @@ -1,24 +1,248 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -instcombine -S | FileCheck %s ; rdar://10770603 -; (x & y) | (x ^ y) -> x | y -define i64 @or(i64 %x, i64 %y) nounwind uwtable readnone ssp { +; (x & y) | (x ^ y) -> x | y + +define i64 @or(i64 %x, i64 %y) { +; CHECK-LABEL: @or( +; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i64 [[TMP1]] +; %1 = and i64 %y, %x %2 = xor i64 %y, %x %3 = add i64 %1, %2 ret i64 %3 -; CHECK-LABEL: @or( -; CHECK: or i64 -; CHECK-NEXT: ret } -; (x & y) + (x ^ y) -> x | y -define i64 @or2(i64 %x, i64 %y) nounwind uwtable readnone ssp { +; (x & y) + (x ^ y) -> x | y + +define i64 @or2(i64 %x, i64 %y) { +; CHECK-LABEL: @or2( +; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: ret i64 [[TMP1]] +; %1 = and i64 %y, %x %2 = xor i64 %y, %x %3 = or i64 %1, %2 ret i64 %3 -; CHECK-LABEL: @or2( -; CHECK: or i64 -; CHECK-NEXT: ret } + +; PR37098 - https://bugs.llvm.org/show_bug.cgi?id=37098 +; Reassociate bitwise logic to eliminate a shift. +; There are 4 commuted * 3 shift ops * 3 logic ops = 36 potential variations of this fold. +; Mix the commutation options to provide coverage using less tests. + +define i8 @and_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @and_shl( +; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = and i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = shl i8 %x, %shamt + %sy = shl i8 %y, %shamt + %a = and i8 %sx, %z + %r = and i8 %sy, %a + ret i8 %r +} + +define i8 @or_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @or_shl( +; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[A]], [[SY]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = shl i8 %x, %shamt + %sy = shl i8 %y, %shamt + %a = or i8 %sx, %z + %r = or i8 %a, %sy + ret i8 %r +} + +define i8 @xor_shl(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { +; CHECK-LABEL: @xor_shl( +; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]] +; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = xor i8 [[Z]], [[SX]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]] +; CHECK-NEXT: ret i8 [[R]] +; + %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization + %sx = shl i8 %x, %shamt + %sy = shl i8 %y, %shamt + %a = xor i8 %z, %sx + %r = xor i8 %a, %sy + ret i8 %r +} + +define i8 @and_lshr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { +; CHECK-LABEL: @and_lshr( +; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]] +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = and i8 [[Z]], [[SX]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = and i8 %z, %sx + %r = and i8 %sy, %a + ret i8 %r +} + +define i8 @or_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @or_lshr( +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = or i8 %sx, %z + %r = or i8 %sy, %a + ret i8 %r +} + +define i8 @xor_lshr(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @xor_lshr( +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = xor i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = xor i8 %sx, %z + %r = xor i8 %a, %sy + ret i8 %r +} + +define i8 @and_ashr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { +; CHECK-LABEL: @and_ashr( +; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]] +; CHECK-NEXT: [[SX:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = and i8 [[Z]], [[SX]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[A]], [[SY]] +; CHECK-NEXT: ret i8 [[R]] +; + %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization + %sx = ashr i8 %x, %shamt + %sy = ashr i8 %y, %shamt + %a = and i8 %z, %sx + %r = and i8 %a, %sy + ret i8 %r +} + +define i8 @or_ashr(i8 %x, i8 %y, i8 %zarg, i8 %shamt) { +; CHECK-LABEL: @or_ashr( +; CHECK-NEXT: [[Z:%.*]] = sdiv i8 42, [[ZARG:%.*]] +; CHECK-NEXT: [[SX:%.*]] = ashr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = ashr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[Z]], [[SX]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %z = sdiv i8 42, %zarg ; thwart complexity-based canonicalization + %sx = ashr i8 %x, %shamt + %sy = ashr i8 %y, %shamt + %a = or i8 %z, %sx + %r = or i8 %sy, %a + ret i8 %r +} + +define <2 x i8> @xor_ashr(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z, <2 x i8> %shamt) { +; CHECK-LABEL: @xor_ashr( +; CHECK-NEXT: [[SX:%.*]] = ashr <2 x i8> [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = ashr <2 x i8> [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = xor <2 x i8> [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = xor <2 x i8> [[A]], [[SY]] +; CHECK-NEXT: ret <2 x i8> [[R]] +; + %sx = ashr <2 x i8> %x, %shamt + %sy = ashr <2 x i8> %y, %shamt + %a = xor <2 x i8> %sx, %z + %r = xor <2 x i8> %a, %sy + ret <2 x i8> %r +} + +; Negative test - different logic ops + +define i8 @or_and_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @or_and_shl( +; CHECK-NEXT: [[SX:%.*]] = shl i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = and i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = shl i8 %x, %shamt + %sy = shl i8 %y, %shamt + %a = or i8 %sx, %z + %r = and i8 %sy, %a + ret i8 %r +} + +; Negative test - different shift ops + +define i8 @or_lshr_shl(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @or_lshr_shl( +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = shl i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[A]], [[SY]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, %shamt + %sy = shl i8 %y, %shamt + %a = or i8 %sx, %z + %r = or i8 %a, %sy + ret i8 %r +} + +; Negative test - different shift amounts + +define i8 @or_lshr_shamt2(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @or_lshr_shamt2( +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], 5 +; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[A:%.*]] = or i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = or i8 [[SY]], [[A]] +; CHECK-NEXT: ret i8 [[R]] +; + %sx = lshr i8 %x, 5 + %sy = lshr i8 %y, %shamt + %a = or i8 %sx, %z + %r = or i8 %sy, %a + ret i8 %r +} + +; Negative test - multi-use + +define i8 @xor_lshr_multiuse(i8 %x, i8 %y, i8 %z, i8 %shamt) { +; CHECK-LABEL: @xor_lshr_multiuse( +; CHECK-NEXT: [[SX:%.*]] = lshr i8 [[X:%.*]], [[SHAMT:%.*]] +; CHECK-NEXT: [[SY:%.*]] = lshr i8 [[Y:%.*]], [[SHAMT]] +; CHECK-NEXT: [[A:%.*]] = xor i8 [[SX]], [[Z:%.*]] +; CHECK-NEXT: [[R:%.*]] = xor i8 [[A]], [[SY]] +; CHECK-NEXT: [[R2:%.*]] = sdiv i8 [[A]], [[R]] +; CHECK-NEXT: ret i8 [[R2]] +; + %sx = lshr i8 %x, %shamt + %sy = lshr i8 %y, %shamt + %a = xor i8 %sx, %z + %r = xor i8 %a, %sy + %r2 = sdiv i8 %a, %r + ret i8 %r2 +} +