[InstCombine] Negator: `extractelement` is negatible if src is negatible
authorRoman Lebedev <lebedev.ri@gmail.com>
Wed, 20 May 2020 18:01:28 +0000 (21:01 +0300)
committerRoman Lebedev <lebedev.ri@gmail.com>
Wed, 20 May 2020 18:44:31 +0000 (21:44 +0300)
----------------------------------------
define i4 @negate_extractelement(<2 x i4> %x, i32 %y, i4 %z) {
%0:
  %t0 = sub <2 x i4> { 0, 0 }, %x
  call void @use_v2i4(<2 x i4> %t0)
  %t1 = extractelement <2 x i4> %t0, i32 %y
  %t2 = sub i4 %z, %t1
  ret i4 %t2
}
=>
define i4 @negate_extractelement(<2 x i4> %x, i32 %y, i4 %z) {
%0:
  %t0 = sub <2 x i4> { 0, 0 }, %x
  call void @use_v2i4(<2 x i4> %t0)
  %t1.neg = extractelement <2 x i4> %x, i32 %y
  %t2 = add i4 %t1.neg, %z
  ret i4 %t2
}
Transformation seems to be correct!

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp
llvm/test/Transforms/InstCombine/sub-of-negatible.ll

index c393a63..1d26edb 100644 (file)
@@ -295,6 +295,15 @@ LLVM_NODISCARD Value *Negator::visit(Value *V, unsigned Depth) {
     return Builder.CreateShuffleVector(NegOp0, NegOp1, Shuf->getShuffleMask(),
                                        I->getName() + ".neg");
   }
+  case Instruction::ExtractElement: {
+    // `extractelement` is negatible if source operand is negatible.
+    auto *EEI = cast<ExtractElementInst>(I);
+    Value *NegVector = visit(EEI->getVectorOperand(), Depth + 1);
+    if (!NegVector) // Early return.
+      return nullptr;
+    return Builder.CreateExtractElement(NegVector, EEI->getIndexOperand(),
+                                        I->getName() + ".neg");
+  }
   case Instruction::Trunc: {
     // `trunc` is negatible if its operand is negatible.
     Value *NegOp = visit(I->getOperand(0), Depth + 1);
index 9526946..d18e49b 100644 (file)
@@ -921,8 +921,8 @@ define i4 @negate_extractelement(<2 x i4> %x, i32 %y, i4 %z) {
 ; CHECK-LABEL: @negate_extractelement(
 ; CHECK-NEXT:    [[T0:%.*]] = sub <2 x i4> zeroinitializer, [[X:%.*]]
 ; CHECK-NEXT:    call void @use_v2i4(<2 x i4> [[T0]])
-; CHECK-NEXT:    [[T1:%.*]] = extractelement <2 x i4> [[T0]], i32 [[Y:%.*]]
-; CHECK-NEXT:    [[T2:%.*]] = sub i4 [[Z:%.*]], [[T1]]
+; CHECK-NEXT:    [[T1_NEG:%.*]] = extractelement <2 x i4> [[X]], i32 [[Y:%.*]]
+; CHECK-NEXT:    [[T2:%.*]] = add i4 [[T1_NEG]], [[Z:%.*]]
 ; CHECK-NEXT:    ret i4 [[T2]]
 ;
   %t0 = sub <2 x i4> zeroinitializer, %x