From 132ef2be48e9204e8fe4947996fa9df153bea6e4 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Sat, 18 Feb 2017 21:59:09 +0000 Subject: [PATCH] [InstSimplify] add nsw/nuw (xor X, signbit), signbit --> X The change to InstCombine in: https://reviews.llvm.org/D29729 ...exposes this missing fold in InstSimplify, so adding this first to avoid a regression. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295573 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/InstructionSimplify.cpp | 12 +++++++++++- test/Transforms/InstCombine/add.ll | 4 +++- test/Transforms/InstSimplify/AndOrXor.ll | 8 ++------ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 2c7ca6210ad..8fce1630aee 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -557,9 +557,19 @@ static Value *SimplifyAddInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, return Y; // X + ~X -> -1 since ~X = -X-1 + Type *Ty = Op0->getType(); if (match(Op0, m_Not(m_Specific(Op1))) || match(Op1, m_Not(m_Specific(Op0)))) - return Constant::getAllOnesValue(Op0->getType()); + return Constant::getAllOnesValue(Ty); + + // add nsw/nuw (xor Y, signbit), signbit --> Y + // The no-wrapping add guarantees that the top bit will be set by the add. + // Therefore, the xor must be clearing the already set sign bit of Y. + Constant *SignBit = + ConstantInt::get(Ty, APInt::getSignBit(Ty->getScalarSizeInBits())); + if ((isNSW || isNUW) && match(Op1, m_Specific(SignBit)) && + match(Op0, m_Xor(m_Value(Y), m_Specific(SignBit)))) + return Y; /// i1 add -> xor. if (MaxRecurse && Op0->getType()->isIntegerTy(1)) diff --git a/test/Transforms/InstCombine/add.ll b/test/Transforms/InstCombine/add.ll index 03b2c3e8571..c04953d1a41 100644 --- a/test/Transforms/InstCombine/add.ll +++ b/test/Transforms/InstCombine/add.ll @@ -244,7 +244,9 @@ define i32 @test19(i1 %C) { ret i32 %V } -; Add of sign bit -> xor of sign bit. +; This is an InstSimplify fold, but test it here to make sure that +; InstCombine does not prevent the fold. +; With NSW, add of sign bit -> or of sign bit. define i32 @test20(i32 %x) { ; CHECK-LABEL: @test20( diff --git a/test/Transforms/InstSimplify/AndOrXor.ll b/test/Transforms/InstSimplify/AndOrXor.ll index 35fbb88eab2..33fd978277d 100644 --- a/test/Transforms/InstSimplify/AndOrXor.ll +++ b/test/Transforms/InstSimplify/AndOrXor.ll @@ -5,9 +5,7 @@ define <2 x i32> @add_nsw_signbit(<2 x i32> %x) { ; CHECK-LABEL: @add_nsw_signbit( -; CHECK-NEXT: [[Y:%.*]] = xor <2 x i32> %x, -; CHECK-NEXT: [[Z:%.*]] = add nsw <2 x i32> [[Y]], -; CHECK-NEXT: ret <2 x i32> [[Z]] +; CHECK-NEXT: ret <2 x i32> %x ; %y = xor <2 x i32> %x, %z = add nsw <2 x i32> %y, @@ -18,9 +16,7 @@ define <2 x i32> @add_nsw_signbit(<2 x i32> %x) { define <2 x i5> @add_nuw_signbit(<2 x i5> %x) { ; CHECK-LABEL: @add_nuw_signbit( -; CHECK-NEXT: [[Y:%.*]] = xor <2 x i5> %x, -; CHECK-NEXT: [[Z:%.*]] = add nuw <2 x i5> [[Y]], -; CHECK-NEXT: ret <2 x i5> [[Z]] +; CHECK-NEXT: ret <2 x i5> %x ; %y = xor <2 x i5> %x, %z = add nuw <2 x i5> %y, -- 2.50.1