[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