Skip to content

Commit

Permalink
[InstCombine] Fix matchRotate bug when one operand is a ConstantExpr …
Browse files Browse the repository at this point in the history
…shift

This bug seems to be harmless in release builds, but will cause an error in UBSAN
builds or an assertion failure in debug builds.

When it gets to this opcode comparison, it assumes both of the operands are BinaryOperators,
but the prior m_LogicalShift will also match a ConstantExpr. The cast<BinaryOperator> will
assert in a debug build, or reading an invalid value for BinaryOp from memory with
((BinaryOperator*)constantExpr)->getOpcode() will cause an error in a UBSAN build.

The test I added will fail without this change in debug/UBSAN builds, but not in release.

Patch by: @AndrewScheidecker (Andrew Scheidecker)

Differential Revision: https://reviews.llvm.org/D58049

llvm-svn: 353736
  • Loading branch information
rotateright committed Feb 11, 2019
1 parent 4892f06 commit 587fd84
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
10 changes: 7 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Expand Up @@ -1819,14 +1819,18 @@ static Instruction *matchRotate(Instruction &Or) {

// First, find an or'd pair of opposite shifts with the same shifted operand:
// or (lshr ShVal, ShAmt0), (shl ShVal, ShAmt1)
Value *Or0 = Or.getOperand(0), *Or1 = Or.getOperand(1);
BinaryOperator *Or0, *Or1;
if (!match(Or.getOperand(0), m_BinOp(Or0)) ||
!match(Or.getOperand(1), m_BinOp(Or1)))
return nullptr;

Value *ShVal, *ShAmt0, *ShAmt1;
if (!match(Or0, m_OneUse(m_LogicalShift(m_Value(ShVal), m_Value(ShAmt0)))) ||
!match(Or1, m_OneUse(m_LogicalShift(m_Specific(ShVal), m_Value(ShAmt1)))))
return nullptr;

auto ShiftOpcode0 = cast<BinaryOperator>(Or0)->getOpcode();
auto ShiftOpcode1 = cast<BinaryOperator>(Or1)->getOpcode();
BinaryOperator::BinaryOps ShiftOpcode0 = Or0->getOpcode();
BinaryOperator::BinaryOps ShiftOpcode1 = Or1->getOpcode();
if (ShiftOpcode0 == ShiftOpcode1)
return nullptr;

Expand Down
14 changes: 14 additions & 0 deletions llvm/test/Transforms/InstCombine/rotate.ll
Expand Up @@ -689,3 +689,17 @@ define i24 @rotl_select_weird_type(i24 %x, i24 %shamt) {
ret i24 %r
}

; Test that the transform doesn't crash when there's an "or" with a ConstantExpr operand.

@external_global = external global i8

define i32 @rotl_constant_expr(i32 %shamt) {
; CHECK-LABEL: @rotl_constant_expr(
; CHECK-NEXT: [[SHR:%.*]] = lshr i32 ptrtoint (i8* @external_global to i32), [[SHAMT:%.*]]
; CHECK-NEXT: [[R:%.*]] = or i32 [[SHR]], shl (i32 ptrtoint (i8* @external_global to i32), i32 11)
; CHECK-NEXT: ret i32 [[R]]
;
%shr = lshr i32 ptrtoint (i8* @external_global to i32), %shamt
%r = or i32 %shr, shl (i32 ptrtoint (i8* @external_global to i32), i32 11)
ret i32 %r
}

0 comments on commit 587fd84

Please sign in to comment.