From 74442061f27678bb13c47fce60a38d8975f42b5b Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 20 Jun 2018 17:48:43 +0000 Subject: [PATCH] [InstCombine] add vector select of binops tests (PR37806) These represent the most basic requested transform - a matching operand and 2 constant operands. llvm-svn: 335151 --- llvm/test/Transforms/InstCombine/shuffle_select.ll | 256 +++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 llvm/test/Transforms/InstCombine/shuffle_select.ll diff --git a/llvm/test/Transforms/InstCombine/shuffle_select.ll b/llvm/test/Transforms/InstCombine/shuffle_select.ll new file mode 100644 index 0000000..5a9e56b --- /dev/null +++ b/llvm/test/Transforms/InstCombine/shuffle_select.ll @@ -0,0 +1,256 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +; Try to eliminate binops and shuffles when the shuffle is a select in disguise: +; PR37806 - https://bugs.llvm.org/show_bug.cgi?id=37806 + +define <4 x i32> @add(<4 x i32> %v0) { +; CHECK-LABEL: @add( +; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = add <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = add <4 x i32> %v0, + %t2 = add <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; Constant operand 0 (LHS) also works. + +define <4 x i32> @sub(<4 x i32> %v0) { +; CHECK-LABEL: @sub( +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = sub <4 x i32> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sub <4 x i32> , %v0 + %t2 = sub <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; If any element of the shuffle mask operand is undef, that element of the result is undef. +; The shuffle is eliminated in this transform, but we can replace a constant element with undef. + +define <4 x i32> @mul(<4 x i32> %v0) { +; CHECK-LABEL: @mul( +; CHECK-NEXT: [[T1:%.*]] = mul <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = mul <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = mul <4 x i32> %v0, + %t2 = mul <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; Preserve flags when possible. + +define <4 x i32> @shl(<4 x i32> %v0) { +; CHECK-LABEL: @shl( +; CHECK-NEXT: [[T1:%.*]] = shl nuw <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = shl nuw <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = shl nuw <4 x i32> %v0, + %t2 = shl nuw <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; Can't propagate the flag here. + +define <4 x i32> @lshr(<4 x i32> %v0) { +; CHECK-LABEL: @lshr( +; CHECK-NEXT: [[T1:%.*]] = lshr exact <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = lshr <4 x i32> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = lshr exact <4 x i32> , %v0 + %t2 = lshr <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; Try weird types. + +define <3 x i32> @ashr(<3 x i32> %v0) { +; CHECK-LABEL: @ashr( +; CHECK-NEXT: [[T1:%.*]] = ashr <3 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = ashr <3 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <3 x i32> [[T1]], <3 x i32> [[T2]], <3 x i32> +; CHECK-NEXT: ret <3 x i32> [[T3]] +; + %t1 = ashr <3 x i32> %v0, + %t2 = ashr <3 x i32> %v0, + %t3 = shufflevector <3 x i32> %t1, <3 x i32> %t2, <3 x i32> + ret <3 x i32> %t3 +} + +define <3 x i42> @and(<3 x i42> %v0) { +; CHECK-LABEL: @and( +; CHECK-NEXT: [[T1:%.*]] = and <3 x i42> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = and <3 x i42> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <3 x i42> [[T1]], <3 x i42> [[T2]], <3 x i32> +; CHECK-NEXT: ret <3 x i42> [[T3]] +; + %t1 = and <3 x i42> %v0, + %t2 = and <3 x i42> %v0, + %t3 = shufflevector <3 x i42> %t1, <3 x i42> %t2, <3 x i32> + ret <3 x i42> %t3 +} + +; It doesn't matter if the intermediate ops have extra uses. + +declare void @use_v4i32(<4 x i32>) + +define <4 x i32> @or(<4 x i32> %v0) { +; CHECK-LABEL: @or( +; CHECK-NEXT: [[T1:%.*]] = or <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = or <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: call void @use_v4i32(<4 x i32> [[T1]]) +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = or <4 x i32> %v0, + %t2 = or <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + call void @use_v4i32(<4 x i32> %t1) + ret <4 x i32> %t3 +} + +define <4 x i32> @xor(<4 x i32> %v0) { +; CHECK-LABEL: @xor( +; CHECK-NEXT: [[T1:%.*]] = xor <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = xor <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: call void @use_v4i32(<4 x i32> [[T2]]) +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = xor <4 x i32> %v0, + %t2 = xor <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + call void @use_v4i32(<4 x i32> %t2) + ret <4 x i32> %t3 +} + +define <4 x i32> @udiv(<4 x i32> %v0) { +; CHECK-LABEL: @udiv( +; CHECK-NEXT: [[T1:%.*]] = udiv <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = udiv <4 x i32> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: call void @use_v4i32(<4 x i32> [[T1]]) +; CHECK-NEXT: call void @use_v4i32(<4 x i32> [[T2]]) +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = udiv <4 x i32> , %v0 + %t2 = udiv <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + call void @use_v4i32(<4 x i32> %t1) + call void @use_v4i32(<4 x i32> %t2) + ret <4 x i32> %t3 +} + +; Div/rem need special handling if the shuffle has undef elements. + +define <4 x i32> @sdiv(<4 x i32> %v0) { +; CHECK-LABEL: @sdiv( +; CHECK-NEXT: [[T1:%.*]] = sdiv <4 x i32> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = sdiv <4 x i32> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = sdiv <4 x i32> %v0, + %t2 = sdiv <4 x i32> %v0, + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @urem(<4 x i32> %v0) { +; CHECK-LABEL: @urem( +; CHECK-NEXT: [[T1:%.*]] = urem <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = urem <4 x i32> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = urem <4 x i32> , %v0 + %t2 = urem <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +define <4 x i32> @srem(<4 x i32> %v0) { +; CHECK-LABEL: @srem( +; CHECK-NEXT: [[T1:%.*]] = srem <4 x i32> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = srem <4 x i32> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x i32> [[T1]], <4 x i32> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x i32> [[T3]] +; + %t1 = srem <4 x i32> , %v0 + %t2 = srem <4 x i32> , %v0 + %t3 = shufflevector <4 x i32> %t1, <4 x i32> %t2, <4 x i32> + ret <4 x i32> %t3 +} + +; Try FP ops/types. + +define <4 x float> @fadd(<4 x float> %v0) { +; CHECK-LABEL: @fadd( +; CHECK-NEXT: [[T1:%.*]] = fadd <4 x float> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = fadd <4 x float> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x float> [[T1]], <4 x float> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[T3]] +; + %t1 = fadd <4 x float> %v0, + %t2 = fadd <4 x float> %v0, + %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> + ret <4 x float> %t3 +} + +define <4 x double> @fsub(<4 x double> %v0) { +; CHECK-LABEL: @fsub( +; CHECK-NEXT: [[T1:%.*]] = fsub <4 x double> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fsub <4 x double> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x double> [[T3]] +; + %t1 = fsub <4 x double> , %v0 + %t2 = fsub <4 x double> , %v0 + %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> + ret <4 x double> %t3 +} + +; Union any FMF. + +define <4 x float> @fmul(<4 x float> %v0) { +; CHECK-LABEL: @fmul( +; CHECK-NEXT: [[T1:%.*]] = fmul nnan ninf <4 x float> [[V0:%.*]], +; CHECK-NEXT: [[T2:%.*]] = fmul nnan ninf <4 x float> [[V0]], +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x float> [[T1]], <4 x float> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x float> [[T3]] +; + %t1 = fmul nnan ninf <4 x float> %v0, + %t2 = fmul nnan ninf <4 x float> %v0, + %t3 = shufflevector <4 x float> %t1, <4 x float> %t2, <4 x i32> + ret <4 x float> %t3 +} + +define <4 x double> @fdiv(<4 x double> %v0) { +; CHECK-LABEL: @fdiv( +; CHECK-NEXT: [[T1:%.*]] = fdiv fast <4 x double> , [[V0:%.*]] +; CHECK-NEXT: [[T2:%.*]] = fdiv nnan arcp <4 x double> , [[V0]] +; CHECK-NEXT: [[T3:%.*]] = shufflevector <4 x double> [[T1]], <4 x double> [[T2]], <4 x i32> +; CHECK-NEXT: ret <4 x double> [[T3]] +; + %t1 = fdiv fast <4 x double> , %v0 + %t2 = fdiv nnan arcp <4 x double> , %v0 + %t3 = shufflevector <4 x double> %t1, <4 x double> %t2, <4 x i32> + ret <4 x double> %t3 +} + -- 2.7.4