[llvm] r317510 - [InstCombine] Pull shifts through a select plus binop with constant

Krzysztof Parzyszek via llvm-commits llvm-commits at lists.llvm.org
Mon Nov 6 14:37:10 PST 2017


This may not be trivial for someone unfamiliar with the code.  I can 
check this tomorrow.

-Krzysztof

On 11/6/2017 4:32 PM, Topper, Craig via llvm-commits wrote:
> Thanks. I'll take a look.
> 
> -----Original Message-----
> From: hwennborg at google.com [mailto:hwennborg at google.com] On Behalf Of Hans Wennborg
> Sent: Monday, November 06, 2017 2:29 PM
> To: Topper, Craig <craig.topper at intel.com>
> Cc: llvm-commits <llvm-commits at lists.llvm.org>
> Subject: Re: [llvm] r317510 - [InstCombine] Pull shifts through a select plus binop with constant
> 
> This broke the buildbots, e.g.
> http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/7386
> It seems the CodeGen/Hexagon/loop-idiom/pmpy-mod.ll test hit some assert.
> 
> I've reverted in r317518
> 
> On Mon, Nov 6, 2017 at 1:07 PM, Craig Topper via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>> Author: ctopper
>> Date: Mon Nov  6 13:07:22 2017
>> New Revision: 317510
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=317510&view=rev
>> Log:
>> [InstCombine] Pull shifts through a select plus binop with constant
>>
>> This pulls shifts through a select+binop with a constant where the select conditionally executes the binop. We already do this for just the binop, but not with the select.
>>
>> This can allow us to get the select closer to other selects to enable removing one.
>>
>> Differential Revision: https://reviews.llvm.org/D39222
>>
>> Modified:
>>      llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
>>      llvm/trunk/test/Transforms/InstCombine/shift.ll
>>
>> Modified: llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp?rev=317510&r1=317509&r2=317510&view=diff
>> ==============================================================================
>> --- llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp (original)
>> +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineShifts.cpp Mon Nov  6 13:07:22 2017
>> @@ -310,6 +310,40 @@ static Value *getShiftedValue(Value *V,
>>     }
>>   }
>>
>> +// If this is a bitwise operator or add with a constant RHS we might be able
>> +// to pull it through a shift.
>> +static bool canShiftBinOpWithConstantRHS(BinaryOperator &Shift,
>> +                                         BinaryOperator *BO,
>> +                                         const APInt &C) {
>> +  bool IsValid = true;     // Valid only for And, Or Xor,
>> +  bool HighBitSet = false; // Transform ifhigh bit of constant set?
>> +
>> +  switch (BO->getOpcode()) {
>> +  default: IsValid = false; break;   // Do not perform transform!
>> +  case Instruction::Add:
>> +    IsValid = Shift.getOpcode() == Instruction::Shl;
>> +    break;
>> +  case Instruction::Or:
>> +  case Instruction::Xor:
>> +    HighBitSet = false;
>> +    break;
>> +  case Instruction::And:
>> +    HighBitSet = true;
>> +    break;
>> +  }
>> +
>> +  // If this is a signed shift right, and the high bit is modified
>> +  // by the logical operation, do not perform the transformation.
>> +  // The HighBitSet boolean indicates the value of the high bit of
>> +  // the constant which would cause it to be modified for this
>> +  // operation.
>> +  //
>> +  if (IsValid && Shift.getOpcode() == Instruction::AShr)
>> +    IsValid = C.isNegative() == HighBitSet;
>> +
>> +  return IsValid;
>> +}
>> +
>>   Instruction *InstCombiner::FoldShiftByConstant(Value *Op0, Constant *Op1,
>>                                                  BinaryOperator &I) {
>>     bool isLeftShift = I.getOpcode() == Instruction::Shl;
>> @@ -472,33 +506,7 @@ Instruction *InstCombiner::FoldShiftByCo
>>         // shift is the only use, we can pull it out of the shift.
>>         const APInt *Op0C;
>>         if (match(Op0BO->getOperand(1), m_APInt(Op0C))) {
>> -        bool isValid = true;     // Valid only for And, Or, Xor
>> -        bool highBitSet = false; // Transform if high bit of constant set?
>> -
>> -        switch (Op0BO->getOpcode()) {
>> -        default: isValid = false; break;   // Do not perform transform!
>> -        case Instruction::Add:
>> -          isValid = isLeftShift;
>> -          break;
>> -        case Instruction::Or:
>> -        case Instruction::Xor:
>> -          highBitSet = false;
>> -          break;
>> -        case Instruction::And:
>> -          highBitSet = true;
>> -          break;
>> -        }
>> -
>> -        // If this is a signed shift right, and the high bit is modified
>> -        // by the logical operation, do not perform the transformation.
>> -        // The highBitSet boolean indicates the value of the high bit of
>> -        // the constant which would cause it to be modified for this
>> -        // operation.
>> -        //
>> -        if (isValid && I.getOpcode() == Instruction::AShr)
>> -          isValid = Op0C->isNegative() == highBitSet;
>> -
>> -        if (isValid) {
>> +        if (canShiftBinOpWithConstantRHS(I, Op0BO, *Op0C)) {
>>             Constant *NewRHS = ConstantExpr::get(I.getOpcode(),
>>                                        cast<Constant>(Op0BO->getOperand(1)), Op1);
>>
>> @@ -525,6 +533,53 @@ Instruction *InstCombiner::FoldShiftByCo
>>           return BinaryOperator::CreateSub(NewRHS, NewShift);
>>         }
>>       }
>> +
>> +    // If we have a select that conditionally executes some binary operator,
>> +    // see if we can pull it the select and operator through the shift.
>> +    //
>> +    // For example, turning:
>> +    //   shl (select C, (add X, C1), X), C2
>> +    // Into:
>> +    //   Y = shl X, C2
>> +    //   select C, (add Y, C1 << C2), Y
>> +    Value *Cond;
>> +    BinaryOperator *TBO;
>> +    Value *FalseVal;
>> +    if (match(Op0, m_Select(m_Value(Cond), m_OneUse(m_BinOp(TBO)),
>> +                            m_Value(FalseVal)))) {
>> +      const APInt *C;
>> +      if (!isa<Constant>(FalseVal) && TBO->getOperand(0) == FalseVal &&
>> +          match(TBO->getOperand(1), m_APInt(C)) &&
>> +          canShiftBinOpWithConstantRHS(I, TBO, *C)) {
>> +        Constant *NewRHS = ConstantExpr::get(I.getOpcode(),
>> +                                       cast<Constant>(TBO->getOperand(1)), Op1);
>> +
>> +        Value *NewShift =
>> +          Builder.CreateBinOp(I.getOpcode(), FalseVal, Op1);
>> +        Value *NewOp = Builder.CreateBinOp(TBO->getOpcode(), NewShift,
>> +                                           NewRHS);
>> +        return SelectInst::Create(Cond, NewOp, NewShift);
>> +      }
>> +    }
>> +
>> +    BinaryOperator *FBO;
>> +    Value *TrueVal;
>> +    if (match(Op0, m_Select(m_Value(Cond), m_Value(TrueVal),
>> +                            m_OneUse(m_BinOp(FBO))))) {
>> +      const APInt *C;
>> +      if (!isa<Constant>(TrueVal) && FBO->getOperand(0) == TrueVal &&
>> +          match(FBO->getOperand(1), m_APInt(C)) &&
>> +          canShiftBinOpWithConstantRHS(I, FBO, *C)) {
>> +        Constant *NewRHS = ConstantExpr::get(I.getOpcode(),
>> +                                       cast<Constant>(FBO->getOperand(1)), Op1);
>> +
>> +        Value *NewShift =
>> +          Builder.CreateBinOp(I.getOpcode(), TrueVal, Op1);
>> +        Value *NewOp = Builder.CreateBinOp(FBO->getOpcode(), NewShift,
>> +                                           NewRHS);
>> +        return SelectInst::Create(Cond, NewShift, NewOp);
>> +      }
>> +    }
>>     }
>>
>>     return nullptr;
>>
>> Modified: llvm/trunk/test/Transforms/InstCombine/shift.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/shift.ll?rev=317510&r1=317509&r2=317510&view=diff
>> ==============================================================================
>> --- llvm/trunk/test/Transforms/InstCombine/shift.ll (original)
>> +++ llvm/trunk/test/Transforms/InstCombine/shift.ll Mon Nov  6 13:07:22 2017
>> @@ -1332,3 +1332,263 @@ define i7 @test65(i7 %a, i7 %b) {
>>     %y = and i7 %x, 1 ; this extracts the lsb which should be 0 because we shifted an even number of bits and all even bits of the shift input are 0.
>>     ret i7 %y
>>   }
>> +
>> +define i32 @shl_select_add_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_add_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = add i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_add_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_add_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = add i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = add i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_and_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_and_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_and_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_and_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_and_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_and_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_and_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_and_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_and_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_and_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -1073741821
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 2147483655
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_and_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_and_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = and i32 [[TMP1]], -1073741821
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = and i32 %x, 2147483655
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_or_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_or_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_or_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_or_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_or_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_or_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_or_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_or_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_or_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_or_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_or_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_or_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = or i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = or i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_xor_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_xor_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @shl_select_xor_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @shl_select_xor_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 14
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = shl i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_xor_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_xor_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @lshr_select_xor_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @lshr_select_xor_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = lshr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = lshr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_xor_true(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_xor_true(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP2]], i32 [[TMP1]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %1, i32 %x
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>> +
>> +define i32 @ashr_select_xor_false(i32 %x, i1 %cond) {
>> +; CHECK-LABEL: @ashr_select_xor_false(
>> +; CHECK-NEXT:    [[TMP1:%.*]] = ashr i32 [[X:%.*]], 1
>> +; CHECK-NEXT:    [[TMP2:%.*]] = xor i32 [[TMP1]], 3
>> +; CHECK-NEXT:    [[TMP3:%.*]] = select i1 [[COND:%.*]], i32 [[TMP1]], i32 [[TMP2]]
>> +; CHECK-NEXT:    ret i32 [[TMP3]]
>> +;
>> +  %1 = xor i32 %x, 7
>> +  %2 = select i1 %cond, i32 %x, i32 %1
>> +  %3 = ashr i32 %2, 1
>> +  ret i32 %3
>> +}
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> 

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, 
hosted by The Linux Foundation


More information about the llvm-commits mailing list