Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IR] Remove support for lshr/ashr constant expressions #71955

Merged
merged 1 commit into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 0 additions & 2 deletions llvm/bindings/ocaml/llvm/llvm.ml
Original file line number Diff line number Diff line change
Expand Up @@ -654,8 +654,6 @@ external const_icmp : Icmp.t -> llvalue -> llvalue -> llvalue
external const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue
= "llvm_const_fcmp"
external const_shl : llvalue -> llvalue -> llvalue = "llvm_const_shl"
external const_lshr : llvalue -> llvalue -> llvalue = "llvm_const_lshr"
external const_ashr : llvalue -> llvalue -> llvalue = "llvm_const_ashr"
external const_gep : lltype -> llvalue -> llvalue array -> llvalue
= "llvm_const_gep"
external const_in_bounds_gep : lltype -> llvalue -> llvalue array -> llvalue
Expand Down
10 changes: 0 additions & 10 deletions llvm/bindings/ocaml/llvm/llvm.mli
Original file line number Diff line number Diff line change
Expand Up @@ -1145,16 +1145,6 @@ val const_fcmp : Fcmp.t -> llvalue -> llvalue -> llvalue
See the method [llvm::ConstantExpr::getShl]. *)
val const_shl : llvalue -> llvalue -> llvalue

(** [const_lshr c1 c2] returns the constant integer [c1] right-shifted by the
constant integer [c2] with zero extension.
See the method [llvm::ConstantExpr::getLShr]. *)
val const_lshr : llvalue -> llvalue -> llvalue

(** [const_ashr c1 c2] returns the constant integer [c1] right-shifted by the
constant integer [c2] with sign extension.
See the method [llvm::ConstantExpr::getAShr]. *)
val const_ashr : llvalue -> llvalue -> llvalue

(** [const_gep srcty pc indices] returns the constant [getElementPtr] of [pc]
with source element type [srcty] and the constant integers indices from the
array [indices].
Expand Down
12 changes: 0 additions & 12 deletions llvm/bindings/ocaml/llvm/llvm_ocaml.c
Original file line number Diff line number Diff line change
Expand Up @@ -1233,18 +1233,6 @@ value llvm_const_shl(value LHS, value RHS) {
return to_val(Value);
}

/* llvalue -> llvalue -> llvalue */
value llvm_const_lshr(value LHS, value RHS) {
LLVMValueRef Value = LLVMConstLShr(Value_val(LHS), Value_val(RHS));
return to_val(Value);
}

/* llvalue -> llvalue -> llvalue */
value llvm_const_ashr(value LHS, value RHS) {
LLVMValueRef Value = LLVMConstAShr(Value_val(LHS), Value_val(RHS));
return to_val(Value);
}

/* lltype -> llvalue -> llvalue array -> llvalue */
value llvm_const_gep(value Ty, value ConstantVal, value Indices) {
mlsize_t Length = Wosize_val(Indices);
Expand Down
4 changes: 0 additions & 4 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4693,10 +4693,6 @@ The following is the syntax for constant expressions:
Perform a multiplication on constants.
``shl (LHS, RHS)``
Perform a left shift on constants.
``lshr (LHS, RHS)``
Perform a logical right shift on constants.
``ashr (LHS, RHS)``
Perform an arithmetic right shift on constants.
``xor (LHS, RHS)``
Perform a bitwise xor on constants.

Expand Down
4 changes: 4 additions & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ Changes to the LLVM IR

* ``and``
* ``or``
* ``lshr``
* ``ashr``
* ``zext``
* ``sext``
* ``fptrunc``
Expand Down Expand Up @@ -174,6 +176,8 @@ Changes to the C API

* ``LLVMConstAnd``
* ``LLVMConstOr``
* ``LLVMConstLShr``
* ``LLVMConstAShr``
* ``LLVMConstZExt``
* ``LLVMConstSExt``
* ``LLVMConstZExtOrBitCast``
Expand Down
2 changes: 0 additions & 2 deletions llvm/include/llvm-c/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -2281,8 +2281,6 @@ LLVMValueRef LLVMConstICmp(LLVMIntPredicate Predicate,
LLVMValueRef LLVMConstFCmp(LLVMRealPredicate Predicate,
LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstShl(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant);
LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices);
LLVMValueRef LLVMConstInBoundsGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
Expand Down
10 changes: 0 additions & 10 deletions llvm/include/llvm/IR/Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -1038,8 +1038,6 @@ class ConstantExpr : public Constant {
static Constant *getXor(Constant *C1, Constant *C2);
static Constant *getShl(Constant *C1, Constant *C2, bool HasNUW = false,
bool HasNSW = false);
static Constant *getLShr(Constant *C1, Constant *C2, bool isExact = false);
static Constant *getAShr(Constant *C1, Constant *C2, bool isExact = false);
static Constant *getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced = false);
static Constant *getPtrToInt(Constant *C, Type *Ty,
bool OnlyIfReduced = false);
Expand Down Expand Up @@ -1085,14 +1083,6 @@ class ConstantExpr : public Constant {
return getShl(C1, C2, true, false);
}

static Constant *getExactAShr(Constant *C1, Constant *C2) {
return getAShr(C1, C2, true);
}

static Constant *getExactLShr(Constant *C1, Constant *C2) {
return getLShr(C1, C2, true);
}

/// If C is a scalar/fixed width vector of known powers of 2, then this
/// function returns a new scalar/fixed width vector obtained from logBase2
/// of C. Undef vector elements are set to zero.
Expand Down
12 changes: 4 additions & 8 deletions llvm/lib/AsmParser/LLParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3852,6 +3852,10 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
return error(ID.Loc, "and constexprs are no longer supported");
case lltok::kw_or:
return error(ID.Loc, "or constexprs are no longer supported");
case lltok::kw_lshr:
return error(ID.Loc, "lshr constexprs are no longer supported");
case lltok::kw_ashr:
return error(ID.Loc, "ashr constexprs are no longer supported");
case lltok::kw_fneg:
return error(ID.Loc, "fneg constexprs are no longer supported");
case lltok::kw_select:
Expand Down Expand Up @@ -3910,12 +3914,9 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
case lltok::kw_sub:
case lltok::kw_mul:
case lltok::kw_shl:
case lltok::kw_lshr:
case lltok::kw_ashr:
case lltok::kw_xor: {
bool NUW = false;
bool NSW = false;
bool Exact = false;
unsigned Opc = Lex.getUIntVal();
Constant *Val0, *Val1;
Lex.Lex();
Expand All @@ -3928,10 +3929,6 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
if (EatIfPresent(lltok::kw_nuw))
NUW = true;
}
} else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv ||
Opc == Instruction::LShr || Opc == Instruction::AShr) {
if (EatIfPresent(lltok::kw_exact))
Exact = true;
}
if (parseToken(lltok::lparen, "expected '(' in binary constantexpr") ||
parseGlobalTypeAndValue(Val0) ||
Expand All @@ -3948,7 +3945,6 @@ bool LLParser::parseValID(ValID &ID, PerFunctionState *PFS, Type *ExpectedTy) {
unsigned Flags = 0;
if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap;
if (Exact) Flags |= PossiblyExactOperator::IsExact;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated musing: I've been wondering for a long time if we couldn't turn or and and into possibly exact operators with the meaning of exact being "the set / unset bits of the operands are disjoint". The idea being that this might help sometimes with issues caused by LLVM eagerly replacing add with or in address expressions.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 I've wondered something similar.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a good addition to me. At least for or, the utility is pretty clear. For and, I'm not sure where we could make use of this property.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't have a concrete use for and. The motivation is simply to close over deMorgan's laws.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to work on a patch for this. Do we want to use 'exact' or have a new keyword like 'disjoint'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would lean towards a new flag. The usage will be quite different from the existing exact flag.

ID.ConstantVal = ConstantExpr::get(Opc, Val0, Val1, Flags);
ID.Kind = ValID::t_Constant;
return false;
Expand Down
23 changes: 0 additions & 23 deletions llvm/lib/IR/ConstantFold.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,29 +155,6 @@ static Constant *ExtractConstantBytes(Constant *C, unsigned ByteStart,

switch (CE->getOpcode()) {
default: return nullptr;
case Instruction::LShr: {
ConstantInt *Amt = dyn_cast<ConstantInt>(CE->getOperand(1));
if (!Amt)
return nullptr;
APInt ShAmt = Amt->getValue();
// Cannot analyze non-byte shifts.
if ((ShAmt & 7) != 0)
return nullptr;
ShAmt.lshrInPlace(3);

// If the extract is known to be all zeros, return zero.
if (ShAmt.uge(CSize - ByteStart))
return Constant::getNullValue(
IntegerType::get(CE->getContext(), ByteSize * 8));
// If the extract is known to be fully in the input, extract it.
if (ShAmt.ule(CSize - (ByteStart + ByteSize)))
return ExtractConstantBytes(CE->getOperand(0),
ByteStart + ShAmt.getZExtValue(), ByteSize);

// TODO: Handle the 'partially zero' case.
return nullptr;
}

case Instruction::Shl: {
ConstantInt *Amt = dyn_cast<ConstantInt>(CE->getOperand(1));
if (!Amt)
Expand Down
14 changes: 2 additions & 12 deletions llvm/lib/IR/Constants.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2160,13 +2160,13 @@ bool ConstantExpr::isSupportedBinOp(unsigned Opcode) {
case Instruction::FRem:
case Instruction::And:
case Instruction::Or:
case Instruction::LShr:
case Instruction::AShr:
return false;
case Instruction::Add:
case Instruction::Sub:
case Instruction::Mul:
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
case Instruction::Xor:
return true;
default:
Expand Down Expand Up @@ -2482,16 +2482,6 @@ Constant *ConstantExpr::getShl(Constant *C1, Constant *C2,
return get(Instruction::Shl, C1, C2, Flags);
}

Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2, bool isExact) {
return get(Instruction::LShr, C1, C2,
isExact ? PossiblyExactOperator::IsExact : 0);
}

Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2, bool isExact) {
return get(Instruction::AShr, C1, C2,
isExact ? PossiblyExactOperator::IsExact : 0);
}

Constant *ConstantExpr::getExactLogBase2(Constant *C) {
Type *Ty = C->getType();
const APInt *IVal;
Expand Down
10 changes: 0 additions & 10 deletions llvm/lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1712,16 +1712,6 @@ LLVMValueRef LLVMConstShl(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) {
unwrap<Constant>(RHSConstant)));
}

LLVMValueRef LLVMConstLShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) {
return wrap(ConstantExpr::getLShr(unwrap<Constant>(LHSConstant),
unwrap<Constant>(RHSConstant)));
}

LLVMValueRef LLVMConstAShr(LLVMValueRef LHSConstant, LLVMValueRef RHSConstant) {
return wrap(ConstantExpr::getAShr(unwrap<Constant>(LHSConstant),
unwrap<Constant>(RHSConstant)));
}

LLVMValueRef LLVMConstGEP2(LLVMTypeRef Ty, LLVMValueRef ConstantVal,
LLVMValueRef *ConstantIndices, unsigned NumIndices) {
ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/Assembler/2003-05-21-MalformedShiftCrash.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
; RUN: not llvm-as < %s > /dev/null 2> %t
; RUN: grep "constexpr requires integer or integer vector operands" %t

@0 = global i32 ashr (float 1.0, float 2.0)
@0 = global i32 shl (float 1.0, float 2.0)
6 changes: 0 additions & 6 deletions llvm/test/Assembler/2003-11-05-ConstantExprShift.ll

This file was deleted.

10 changes: 0 additions & 10 deletions llvm/test/Assembler/flags.ll
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,6 @@ define i64 @mul_both_ce() {
ret i64 mul nuw nsw (i64 ptrtoint (ptr @addr to i64), i64 91)
}

define i64 @ashr_exact_ce() {
; CHECK: ret i64 ashr exact (i64 ptrtoint (ptr @addr to i64), i64 9)
ret i64 ashr exact (i64 ptrtoint (ptr @addr to i64), i64 9)
}

define i64 @lshr_exact_ce() {
; CHECK: ret i64 lshr exact (i64 ptrtoint (ptr @addr to i64), i64 9)
ret i64 lshr exact (i64 ptrtoint (ptr @addr to i64), i64 9)
}

define ptr @gep_nw_ce() {
; CHECK: ret ptr getelementptr inbounds (i64, ptr @addr, i64 171)
ret ptr getelementptr inbounds (i64, ptr @addr, i64 171)
Expand Down
20 changes: 0 additions & 20 deletions llvm/test/Assembler/vector-shift.ll
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,3 @@ entry:
%cmp = ashr <4 x i32> %a, %b ; <4 x i32> [#uses=1]
ret <4 x i32> %cmp
}

; Constant expressions: these should be folded.

; CHECK: @foo_ce
; CHECK: ret <2 x i64> <i64 40, i64 192>
define <2 x i64> @foo_ce() nounwind {
ret <2 x i64> shl (<2 x i64> <i64 5, i64 6>, <2 x i64> <i64 3, i64 5>)
}

; CHECK: @bar_ce
; CHECK: ret <2 x i64> <i64 42, i64 11>
define <2 x i64> @bar_ce() nounwind {
ret <2 x i64> lshr (<2 x i64> <i64 340, i64 380>, <2 x i64> <i64 3, i64 5>)
}

; CHECK: baz_ce
; CHECK: ret <2 x i64> <i64 71, i64 12>
define <2 x i64> @baz_ce() nounwind {
ret <2 x i64> ashr (<2 x i64> <i64 573, i64 411>, <2 x i64> <i64 3, i64 5>)
}
6 changes: 5 additions & 1 deletion llvm/test/CodeGen/AArch64/fold-global-offsets.ll
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ define i32 @f7() {
; GISEL-NEXT: ret

entry:
%l = load i32, ptr getelementptr (i32, ptr inttoptr (i64 trunc (i128 lshr (i128 bitcast (<2 x i64> <i64 undef, i64 ptrtoint (ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @x3, i64 0, inrange i32 1, i64 2) to i64)> to i128), i128 64) to i64) to ptr), i64 5)
%lshr = lshr i128 bitcast (<2 x i64> <i64 undef, i64 ptrtoint (ptr getelementptr inbounds ({ [9 x ptr], [8 x ptr] }, ptr @x3, i64 0, inrange i32 1, i64 2) to i64)> to i128), 64
%trunc = trunc i128 %lshr to i64
%inttoptr = inttoptr i64 %trunc to ptr
%gep = getelementptr i32, ptr %inttoptr, i64 5
%l = load i32, ptr %gep
ret i32 %l
}
5 changes: 4 additions & 1 deletion llvm/test/CodeGen/X86/2009-01-18-ConstantExprCrash.ll
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ bb4.i.i70: ; preds = %bb4.i.i70, %bb.i51
br i1 false, label %_ZN11xercesc_2_59XMLString9stringLenEPKt.exit.i73, label %bb4.i.i70

_ZN11xercesc_2_59XMLString9stringLenEPKt.exit.i73: ; preds = %bb4.i.i70
%0 = load i16, ptr getelementptr ([7 x i16], ptr @_ZN11xercesc_2_5L17gIdeographicCharsE, i32 0, i32 add (i32 ashr (i32 sub (i32 ptrtoint (ptr getelementptr ([7 x i16], ptr @_ZN11xercesc_2_5L17gIdeographicCharsE, i32 0, i32 4) to i32), i32 ptrtoint (ptr @_ZN11xercesc_2_5L17gIdeographicCharsE to i32)), i32 1), i32 1)), align 4 ; <i16> [#uses=0]
%ashr = ashr i32 sub (i32 ptrtoint (ptr getelementptr ([7 x i16], ptr @_ZN11xercesc_2_5L17gIdeographicCharsE, i32 0, i32 4) to i32), i32 ptrtoint (ptr @_ZN11xercesc_2_5L17gIdeographicCharsE to i32)), 1
%add = add i32 %ashr, 1
%gep = getelementptr [7 x i16], ptr @_ZN11xercesc_2_5L17gIdeographicCharsE, i32 0, i32 %add
%0 = load i16, ptr %gep, align 4
br label %bb4.i5.i141

bb4.i5.i141: ; preds = %bb4.i5.i141, %_ZN11xercesc_2_59XMLString9stringLenEPKt.exit.i73
Expand Down
10 changes: 8 additions & 2 deletions llvm/test/CodeGen/X86/pre-coalesce-2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ if.end5: ; preds = %while.body
br i1 %cmp6, label %if.end14, label %cleanup.thread40

if.end14: ; preds = %if.end5
%22 = load i8, ptr inttoptr (i64 add (i64 lshr (i64 ptrtoint (ptr @a to i64), i64 3), i64 2147450880) to ptr)
%lshr1 = lshr i64 ptrtoint (ptr @a to i64), 3
%add1 = add i64 %lshr1, 2147450880
%inttoptr1 = inttoptr i64 %add1 to ptr
%22 = load i8, ptr %inttoptr1
%23 = icmp ne i8 %22, 0
br i1 %23, label %24, label %25

Expand Down Expand Up @@ -177,7 +180,10 @@ cleanup.thread40: ; preds = %if.end5
br label %enoent

cleanup: ; preds = %while.body
%61 = load i8, ptr inttoptr (i64 add (i64 lshr (i64 ptrtoint (ptr @b to i64), i64 3), i64 2147450880) to ptr)
%lshr2 = lshr i64 ptrtoint (ptr @b to i64), 3
%add2 = add i64 %lshr2, 2147450880
%inttoptr2 = inttoptr i64 %add2 to ptr
%61 = load i8, ptr %inttoptr2
%62 = icmp ne i8 %61, 0
br i1 %62, label %63, label %66

Expand Down
9 changes: 6 additions & 3 deletions llvm/test/DebugInfo/AArch64/asan-stack-vars.mir
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,8 @@
store i8* %_cmd, i8** %_cmd.addr, align 8
call void @llvm.dbg.declare(metadata i8** %_cmd.addr, metadata !48, metadata !DIExpression()), !dbg !47
%29 = load %struct._class_t*, %struct._class_t** @"OBJC_CLASSLIST_REFERENCES_$_", align 8, !dbg !50
%30 = add i64 lshr (i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_ to i64), i64 3), %1, !dbg !50
%lshr1 = lshr i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_ to i64), 3, !dbg !50
%30 = add i64 %lshr1, %1, !dbg !50
%31 = inttoptr i64 %30 to i8*, !dbg !50
%32 = load i8, i8* %31, !dbg !50
%33 = icmp ne i8 %32, 0, !dbg !50
Expand All @@ -149,7 +150,8 @@
%37 = bitcast %struct._class_t* %29 to i8*, !dbg !50
%call = call i8* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to i8* (i8*, i8*)*)(i8* %37, i8* %36), !dbg !50
%38 = bitcast i8* %call to %0*, !dbg !50
%39 = add i64 lshr (i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_.2 to i64), i64 3), %1, !dbg !51
%lshr2 = lshr i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_.2 to i64), 3, !dbg !51
%39 = add i64 %lshr2, %1, !dbg !51
%40 = inttoptr i64 %39 to i8*, !dbg !51
%41 = load i8, i8* %40, !dbg !51
%42 = icmp ne i8 %41, 0, !dbg !51
Expand Down Expand Up @@ -197,7 +199,8 @@
; <label>:65: ; preds = %55
store %0* %57, %0** %6, align 8, !dbg !44
%66 = load %0*, %0** %6, align 8, !dbg !52
%67 = add i64 lshr (i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_.4 to i64), i64 3), %1, !dbg !53
%lshr3 = lshr i64 ptrtoint (i8** @OBJC_SELECTOR_REFERENCES_.4 to i64), 3, !dbg !53
%67 = add i64 %lshr3, %1, !dbg !53
%68 = inttoptr i64 %67 to i8*, !dbg !53
%69 = load i8, i8* %68, !dbg !53
%70 = icmp ne i8 %69, 0, !dbg !53
Expand Down
7 changes: 5 additions & 2 deletions llvm/test/Transforms/InstCombine/and-or.ll
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,13 @@ define <2 x i8> @and_or_hoist_mask_commute_vec_splat(<2 x i8> %a, <2 x i8> %b) {

define i32 @pr64114_and_xor_hoist_mask_constexpr() {
; CHECK-LABEL: @pr64114_and_xor_hoist_mask_constexpr(
; CHECK-NEXT: [[AND:%.*]] = and i32 xor (i32 lshr (i32 ptrtoint (ptr @g to i32), i32 8), i32 ptrtoint (ptr @g to i32)), 1
; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 ptrtoint (ptr @g to i32), 8
; CHECK-NEXT: [[AND:%.*]] = and i32 [[LSHR]], 1
; CHECK-NEXT: ret i32 [[AND]]
;
%and = and i32 xor (i32 lshr (i32 ptrtoint (ptr @g to i32), i32 8), i32 ptrtoint (ptr @g to i32)), 1
%lshr = lshr i32 ptrtoint (ptr @g to i32), 8
%xor = xor i32 %lshr, ptrtoint (ptr @g to i32)
%and = and i32 %xor, 1
ret i32 %and
}

Expand Down